SQLite: CASE within FROM section - sqlite

I need to select the MCUs table if UserID = 7 does not exist in the table. Please help me, what am I doing wrong?
SELECT
MCUs.MCUID
FROM
CASE
WHEN ReqMCUDevs.UserID = 7 THEN
MCUs
INNER JOIN MCUDevs
ON MCUs.MCUID = MCUDevs.MCUID
INNER JOIN ReqMCUDevs
ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
ELSE
MCUs
END
I need the resunt ot this query if UserID=7 exists
SELECT
MCUs.MCUID
FROM
MCUs
INNER JOIN MCUDevs
ON MCUs.MCUID = MCUDevs.MCUID
INNER JOIN ReqMCUDevs
ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE
ReqMCUDevs.UserID = 7
and this query if not
SELECT
MCUs.MCUID
FROM
MCUs
database schema:
The easiest solution is to use two different queries
db = sqlite3.connect("..\\DB.db", isolation_level = None);
c = db.cursor()
#...
c.execute("SELECT UserID FROM ReqMCUDevs WHEN UserID = ?", (UserID,))
if c.fetchall() == []:
c.execute("SELECT MCUID FROM MCUs")
else:
c.execute("""SELECT MCUID FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity <= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = ?""", (UserID,))
but it is really not the answer

CASE works only in expressions (i.e., to compute a value); it is not possible to change the basic structure of a query conditionally.
However, there are different mechanisms to get what you want.
First, the query with the joins does not actually return anything from the joined tables, so it is possible to rewrite it with a subquery:
SELECT Name,
Price
FROM MCUs
WHERE MCUID IN (SELECT MCUID
FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = 7)
ORDER BY Price
Now, we want to ignore this WHERE filter if the subquery is empty.
This can be done with a separate check:
SELECT Name,
Price
FROM MCUs
WHERE MCUID IN (SELECT MCUID
FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = 7)
OR NOT EXISTS (SELECT MCUID
FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = 7)
ORDER BY Price

Related

SQL Server : select distinct records with inner join and where clause

Friends I am stuck in a stored procedure. I am unable to display distinct records.
I have a name USERS and Photos. Both are inner join using userID.
Since the table Photos has multiple records the search result is repeated. Friends can you help me fix this please?
Stored procedure:
ALTER PROCEDURE dbo.homesearch
#gender varchar(6),
#age int,
#age2 int,
#religion varchar(50),
#status varchar(11),
#Country varchar(50),
#City varchar(50)
AS
SELECT
users.userID, photos.filename, users.userName,
users.FirstName, users.LastName, users.nationality,
users.Country, users.City, users.age, users.status
FROM
users
INNER JOIN
photos ON users.userID = photos.userID
WHERE
(users.age >= #age) AND (users.age <= #age2)
AND (users.gender = #gender) AND (users.religion = #religion)
AND (users.status = #status) AND (users.Country = #Country)
AND (users.City = #City)
RETURN
You can do something like this using CROSS APPLY
SELECT u.userID
,u.userName
,P.filename
,u.FirstName
,u.LastName
,u.nationality
,u.Country
,u.City
,u.age
,u.status
FROM users u
CROSS APPLY
(
SELECT TOP 1 photos.filename
FROM photos
WHERE u.userID = userID
ORDER BY photos.SomeColumn --<-- Pick a column here
)p
WHERE (u.age >= #age) AND (u.age <= #age2)
AND (u.gender = #gender) AND (u.religion = #religion)
AND (u.status = #status) AND (u.Country = #Country)
AND (u.City = #City)
Pick a column by which you want to decide which TOP 1 filename you want to pick from Photos table for each user in users table.
Or using CTE
;With P_CTE
AS
(
SELECT TOP UserID, photos.filename,
rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM photos
)
SELECT users.userID, P_CTE.filename, users.userName,
users.FirstName, users.LastName, users.nationality,
users.Country, users.City, users.age, users.status
FROM users INNER JOIN P_CTE
ON users.userID = P_CTE.userID
WHERE (users.age >= #age) AND (users.age <= #age2)
AND (users.gender = #gender) AND (users.religion = #religion)
AND (users.status = #status) AND (users.Country = #Country)
AND (users.City = #City)
AND P_CTE.rn = 1
modify Your select query by :-
SELECT users.userID, photos.filename, users.userName,
users.FirstName, users.LastName, users.nationality,
users.Country, users.City, users.age, users.status
FROM users INNER JOIN photos
ON users.userID = photos.userID
WHERE (users.age >= #age) AND (users.age <= #age2)
AND (users.gender = #gender) AND (users.religion = #religion)
AND (users.status = #status) AND (users.Country = #Country)
AND (users.City = #City)
GROUP BY users.userID, photos.filename, users.userName,
users.FirstName, users.LastName, users.nationality,
users.Country, users.City, users.age, users.status
and it will return unique results.
SELECT users.userID, photos.filename, users.userName,
users.FirstName, users.LastName, users.nationality,
users.Country, users.City, users.age, users.status
FROM users INNER JOIN (SELECT DISTINCT userID FROM photos) AS P
ON users.userID = P.userID
The idea here is to reduce the entries in your Photos table since there are many photos for each user. In my example I'm using max(filename) to get the one with longest name but you can use other criteria here:
SELECT users.userID, P.filename, users.userName,
users.FirstName, users.LastName, users.nationality,
users.Country, users.City, users.age, users.status
FROM users INNER JOIN
(SELECT userID, max(filename) as filename
FROM photos
GROUP BY userID) AS P
ON users.userID = P.userID
WHERE (users.age >= #age) AND (users.age <= #age2)
AND (users.gender = #gender) AND (users.religion = #religion)
AND (users.status = #status) AND (users.Country = #Country)
AND (users.City = #City)
Please clear some points Ali.
Your data is showing something like..
userID userName ......... filename
1 ABC c:/phot1.png
1 ABC c:/phot2.png
1 ABC c:/phot2.png
If i am correct, then their is two possible ways to show your data to make your records distinct.
First
userID userName ......... filename
1 ABC c:/phot1.png,c:/phot2.png,c:/phot2.png
This can be achieved by using for xml path('') OR COALESCE
Second
Show only one photo like:
userID userName ......... filename
1 ABC c:/photo1.png
This can be achieved by applying some condition for photo.

Inner Join in LINQ not working correctly

I have the following tables in this SQL database (some fields are irrelevant to this question):
I have the following LINQ query:
Dim trips = From tr In db.tbl_Trips _
Join ds In db.tbl_tripDeptStations On tr.trip_ID Equals ds.tds_ID _
Where ds.tbl_Station.stn_County = county _
And tr.trip_StartDate >= startDate _
And tr.trip_EndDate <= endDate _
Select tr.trip_Name, tr.trip_StartDate, tr.trip_EndDate, tr.trip_SmallImage, tr.tbl_TourOperator.tourOp_Name
startDate, endDate and county are variables which I have declared in code above (not shown).
I am trying to show trips which have certain departure stations associated, based upon the county which can be found in the station table.
However, when I run the query, I get no results, and no error messages.
I also have this SQL query which works correctly:
SELECT distinct t.trip_ID, t.trip_Name, t.trip_StartDate, toop.tourOp_Name
FROM tbl_Trip AS t
INNER JOIN
(SELECT tds.tds_trip
FROM tbl_tripDeptStation AS tds
INNER JOIN tbl_station AS s
ON tds.tds_Stn = s.stn_ID
WHERE s.stn_county = 'Greater London'
) AS ds
ON t.trip_ID = ds.tds_trip
INNER JOIN tbl_TourOperator AS toop ON t.tourOp_ID = toop.tourop_id
WHERE t.trip_StartDate >= #StartDate AND t.trip_EndDate <= #EndDate
ORDER BY t.trip_
Can anyone shed some light as to where I might be going wrong?
if you're using entity framework,
var ds = from tds in tbl_tripdeptstation
join s in tbl_station on tds.tds_stn equals s.stn_id
where s.stn_country.equals("somecountry")
select new {tds.trip};
var result = (from t in tbl_trip
join ds2 in ds on t.trip_id equals ds2.trip
join toop in tbl_touroperator on t.tourop_id equals toop.tourop_id
where t.trip_start >= SomeDate AND t.trip_enddate <= EndDate
select new { t.trip_ID, t.trip_Name, t.trip_StartDate, toop.tourOp_Name}).Distinct().OrderBy(r => r.trip_);

Query performance issue in oracle

I need to improve my query which has more than 8 joins and consumes lot of total tablespace.
Following is the query:
select r.id, uc.contributor_full_name,s.code,
d.text, ucs.moderation_status, v.url
from review r, user_contribution uc, user_contribution_status ucs,
video v, description d, video_description vd, location_video lv,
accommodation_video av, system s
where r.user_contribution_id = ucs.user_contribution_id and
uc.id = ucs.user_contribution_id and
uc.system_id = s.id and
r.accommodation_id = av.accommodation_id or
r.location_id = lv.location_id and
av.video_id = v.id and
lv.video_id = v.id and
v.id = vd.video_id and
vd.description_id = d.id;
Is there any better way to write this query?
With a query like this it's possible Oracle will default to a whole lot of hash joins and full table scans, which may or may not be a good idea.
+1 to post the explain plan. Until then, don't upvote this answer!
I believe your query is equivalent to this, and it's possible that when you look at the explain plan that you'll see Oracle will convert it to something like this anyway:
select r.id
,uc.contributor_full_name,s.code
,d.text
,ucs.moderation_status
,v.url
from review r
join user_contribution_status ucs on r.user_contribution_id = ucs.user_contribution_id
join user_contribution uc on uc.id = ucs.user_contribution_id
join system s on uc.system_id = s.id
join accommodation_video av on r.accommodation_id = av.accommodation_id
join video_description vd on v.id = vd.video_id
join description d on vd.description_id = d.id
join video v on av.video_id = v.id
union all
select r.id
,uc.contributor_full_name,s.code
,d.text
,ucs.moderation_status
,v.url
from review r
join user_contribution_status ucs on r.user_contribution_id = ucs.user_contribution_id
join user_contribution uc on uc.id = ucs.user_contribution_id
join system s on uc.system_id = s.id
join location_video lv on r.location_id = lv.location_id
join video_description vd on v.id = vd.video_id
join description d on vd.description_id = d.id
join video v on lv.video_id = v.id;
Warning: I may have made some assumptions about constraints (e.g. PK, FK and not null) on some of the ID columns, esp. with regards to accommodation_video and location_video. I removed them from the subclauses with the assumption that they weren't necessary - but this assumption may be wrong.

Asp.Net multiple join tables issue from Sqldatasoruce Query Builder into one gridview

In Visual Studio 2010 with ASP.NET 4, I am trying to join several tables together to put the results in a gridview and details view with sqldatasource. In the sqldatasource wizard I have chosen to specify a custom SQL statement or stored procedure and then in the Query Builder to define complex queries such as JOINs, I have tried to generate a SQL statement to join the problem table with speficific columns from other tables. But when I try to test the query I get an error message which says "Cannot call methods on varchar". I am new to sql statements so please can you advise on what is wrong with the statement.
Here is the generated sql statement below
SELECT Problem.ProblemID, Problem.CustomerID, Problem.Summary,
Problem.DateLogged, Problem.DateUpdated, Status.Status, Priority.Priority,
Technician.Name, Technician.Surname, [Skill Group].[Skill Group],
HelpdeskOperator.Name AS Expr1,
HelpdeskOperator.Surname AS Expr2, Problem.NoteID, Problem.ResolutionID
FROM Problem
INNER JOIN Status ON Problem.StatusID = Status.Status.StatusID
INNER JOIN HelpdeskOperator ON
Problem.HelpdeskID = HelpdeskOperator.HelpdeskID AND Status.StatusID = HelpdeskOperator.StatusID
INNER JOIN Priority ON Problem.PriorityID = Priority.PriorityID
INNER JOIN [Skill Group] ON Problem.SkillGroupID = [Skill Group].SkillGroupID
INNER JOIN Technician ON Problem.ProblemID = Technician.ProblemID
AND Status.StatusID = Technician.StatusID AND
Priority.PriorityID = Technician.PriorityID
AND [Skill Group].SkillGroupID = Technician.SkillGroupID
Thank you in advance
Fixed your query:
SELECT p.ProblemID, p.CustomerID, p.Summary, p.DateLogged, p.DateUpdated, s.Status, pr.Priority, t.Name, t.Surname,
sg.* , ho.Name AS Expr1, ho.Surname AS Expr2, p.NoteID, p.ResolutionID
FROM Problem p
INNER JOIN Status s ON p.StatusID = s.StatusID
INNER JOIN HelpdeskOperator ho ON p.HelpdeskID = ho.HelpdeskID AND s.StatusID = ho.StatusID
INNER JOIN Priority pr ON p.PriorityID = pr.PriorityID
INNER JOIN [Skill Group] sg ON p.SkillGroupID = sg.SkillGroupID
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
AND sg.SkillGroupID = t.SkillGroupID
You had duplicate table identifier in your join clause Status.Status.StatusID
I doubt that your Skill Group table contains column [Skill Group] so changed it to return all values from Skill Group
I just think those were the errors, if not I will need more info about your query and table structure.
EDIT:
First it did not return anything for HelpdeskOperator, look at our query:
INNER JOIN HelpdeskOperator ho ON p.HelpdeskID = ho.HelpdeskID AND s.StatusID = ho.StatusID
that meanse that here is no such HelpdeskOperator record that is assigned to our problem AND statusid, so either problem id points to noexisting helpdeskoperator or statusid of
this operator is different that problem status id.
next is Skill Group
INNER JOIN [Skill Group] sg ON p.SkillGroupID = sg.SkillGroupID
again our problem point to no existing skill group
then Technican
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
AND sg.SkillGroupID = t.SkillGroupID
here is more work as more checks, technicas must be assigned to our problem with given status and priorityt and be in skill group, BUT our skill group is null? so to check if
there is technican for our problem remove AND sg.SkillGroupID = t.SkillGroupID so you get
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
and see if now we get any technican.
I hope this points you into right direction. You must be sure that there are matching record in every joining table.

Modify the sql query in asp.net?

I am using sql server 2005. In this query i want the log-in user detail should also display but it is not displaying .
So please modify the query so that log-in user detail should also display with the help of session[userId].tostring();
Query written by me is:
SELECT DISTINCT MUDMEMBER.PK_ID, MUDMEMBER.EMPLOYEE_ID, LKB.BANK_NAME, MUHD.SALARY_ACCOUNT_NO, MUHD.PF_NO,
MUHD.PAN_NO, MUHD.GENDER, LKD.DESIGNATION_NAME FROM M_LEADERLED MLL INNER JOIN M_USER_DETAILS MUDMEMBER ON
MLL.LED_ID = MUDMEMBER.PK_ID AND MLL.START_DATE <= Getdate() AND MLL.END_DATE > Getdate() AND MLL.LEADER_ID = '1' LEFT OUTER JOIN
M_USER_HR_DETAILS MUHD ON MUHD.FK_USER_ID = MUDMEMBER.PK_ID AND MUHD.IS_ACTIVE =1 LEFT OUTER JOIN
LK_BANKS LKB ON LKB.PK_ID = MUHD.FK_BANK_ID LEFT OUTER JOIN LK_DESIGNATION LKD ON
LKD.DESIGNATION_VALUE = MUHD.FK_DESIGNATION_VALUE AND LKD.FK_ORGANIZATION_ID = 1 AND LKD.IS_ACTIVE = 1 WHERE MUDMEMBER.ACTIVE = 1
ASP.Net Page you can fetch the loggedin user's detail as follows:
SELECT DISTINCT MUDMEMBER.PK_ID, MUDMEMBER.EMPLOYEE_ID, LKB.BANK_NAME, MUHD.SALARY_ACCOUNT_NO, MUHD.PF_NO,
MUHD.PAN_NO, MUHD.GENDER, LKD.DESIGNATION_NAME FROM M_LEADERLED MLL INNER JOIN M_USER_DETAILS MUDMEMBER ON
MLL.LED_ID = MUDMEMBER.PK_ID AND MLL.START_DATE <= Getdate() AND MLL.END_DATE > Getdate()
AND MLL.LEADER_ID = '1' LEFT OUTER JOIN
M_USER_HR_DETAILS MUHD ON MUHD.FK_USER_ID = MUDMEMBER.PK_ID AND MUHD.IS_ACTIVE =1
LEFT OUTER JOIN
LK_BANKS LKB ON LKB.PK_ID = MUHD.FK_BANK_ID LEFT OUTER JOIN LK_DESIGNATION LKD ON
LKD.DESIGNATION_VALUE = MUHD.FK_DESIGNATION_VALUE AND LKD.FK_ORGANIZATION_ID = 1
AND LKD.IS_ACTIVE = 1
WHERE MUDMEMBER.ACTIVE = 1 AND MUDMEMBER.PK_ID ="+Convert.ToInt32(Session["UserId"])+"

Resources