Sql query confusion - sql

I'm stumped on a sql query.
In a query, I have a result set like so:
FooId Name Value SourceLevel SourceId RecordId
-----------------------------------------------------------------
1 'Foo' 10 1 0 1
1 'Foo' 25 3 1 2
2 'Bar' 33 1 0 3
To that query, I pass parameters #Level1Level, #Level2Level, #Level3Level, and #Level1Id, #Level2Id, #Level3Id
(no, these aren't real names, but they illustrate my point).
My query is trying to do a filter like this:
WHERE ((SourceLevel = #Level1Level AND SourceId = #Level1Id)
OR (SourceLevel = #Level2Level AND SourceId = #Level2Id)
OR (SourceLevel = #Level3Level AND SourceId = #Level3Id))
If I pass in parameters like so:
#Level1Level = 1, #Level2Level = 2, #Level3Level = 3
#Level1Id = 0, #Level2Id = 3, #Level3Id = 2
I would want recordIds 1 and 3 back.
But, if I pass in parameters like so:
#Level1Level = 1, #Level2Level = 2, #Level3Level = 3
#Level1Id = 0, #Level2Id = 3, #Level3Id = 1
I would want recordIds 2 and 3 back. Unfortunately, in the second case, I'm getting all 3 records back, which makes sense, because of the OR in my where clause. I can't figure out how to limit my result set to say "only choose SourceLevel 1 if I haven't already matched on SourceLevel 2 or 3".
Anyone have any thoughts, assuming this makes any sense?
To clarify: I want each FooId from my result set, but only the most specific FooId available, based on the SourceLevel parameters passed in.

Here's what I ended up doing:
WHERE
(
(SourceLevel = #Level3Level AND SourceId = #Level3Id)
OR
(
SourceLevel = #Level2Level AND SourceId = #Level2Id
AND NOT EXISTS (SELECT 'X' FROM SourceTable WHERE SourceLevel = #Level3Level And SourceId = #Level3Id AND FooId = SourceTable.FooId)
)
OR
(
SourceLevel = #Level1Level AND SourceId = #Level1Id
AND NOT EXISTS (SELECT 'X' FROM SourceTable WHERE SourceLevel = #Level3Level And SourceId = #Level3Id AND FooId = SourceTable.FooId)
AND NOT EXISTS (SELECT 'X' FROM SourceTable WHERE SourceLevel = #Level2Level And SourceId = #Level2Id AND FooId = SourceTable.FooId)
)
)
This seems to do the filtering I was after...sorry that the question was so confusing. :)

(SourceLevel = 1 AND SourceId = 0) match 1 and 3 records
(SourceLevel = 2 AND SourceId = 3) no matches
(SourceLevel = 3 AND SourceId = 1) match 2 record
All three records will be returned by the query.

I don't see exactly the point and why it's a sql question. But if you want SourceLevel 1 (i call it SL1 now) only if you haven't yet SL2 or SL3...
why don't you try with this:
SL2 OR SL3 OR (NOT SL2 AND NOT SL3 AND SL1)

Related

when category is not null then return record accordingly categoryID. When categoryID is null then all record return

SELECT TOP (#NoofQuetion)
*
FROM
tblQuestion qs
WHERE
qs.IsActive = 1
AND qs.IsDeleted = 0
OR (qs.CategoryID IS NULL AND qs.CategoryID = #CategoryId)
ORDER BY
NEWID()
In this query, #NoofQuestion is is limit apply on record. I want when categoryId IS NULL in where condition then given record all type of categoryId. And when #CategoryId is passed as a parameter, return rows with a matching categoryId only.
For example I pass #CategoryId = 2, I get only record where
ISACTIVE = 1 AND ISDELETED = 0 AND CategoryID = 2
When I pass NULL as #CategoryId, then return all rows where
ISACTIVE = 1 AND ISDELETED = 0
Give me solution.
You swapped the OR and AND. Your WHERE statement should look like
qs.IsActive = 1 AND qs.IsDeleted = 0 AND (qs.CategoryID IS NULL OR qs.CategoryID = #CategoryId)
EDIT:
After some testing, it turns out there's a second problem in your WHERE clause. You're checking if the CategoryId in the table is null, not if your #CategoryId variable is null. After this change and the change mentioned above, your WHERE clause should look like
qs.IsActive = 1 AND qs.IsDeleted = 0 AND (#CategoryID IS NULL OR qs.CategoryID = #CategoryId)
Here's the SQL Fiddle I used to test it.

IF or CASE in WHERE clause of SQL query

My problem is I have a query like this:
SELECT * FROM TABLE1 WHERE STATUSID = #PARAMETER
Then I want to create that query into dynamic one like this:
IF #PARAMETER IS 1 THEN STATUSID = 1
IF #PARAMETER IS 2 THEN STATUSID = 2
IF #PARAMETER IS 3 THEN STATUSID = 1 OR STATUSID = 2
Can anyone give me a sample query how to do this? I just want to do this inside WHERE clause so that I can minimize my line of code.
Use OR
SELECT *
FROM TABLE1
WHERE (STATUSID = 1 and #PARAMETER = 1)
OR (STATUSID = 2 and #PARAMETER = 2)
or (STATUSID in (1,2) and #PARAMETER = 3)
Use CASE Clause to get result :
SELECT * FROM TABLE1 WHERE STATUSID = CASE
WHEN #PARAMETER = 1 THEN 1
WHEN #PARAMETER = 2 THEN 2
WHEN #PARAMETER = 3 THEN STATUSID END
Another solution would be to first check the parameter and then execute the corresponding query.
IF #PARAMETER = 1 THEN SELECT * FROM TABLE1 WHERE STATUSID = 1
IF #PARAMETER = 2 THEN SELECT * FROM TABLE1 WHERE STATUSID = 2
IF #PARAMETER = 3 THEN SELECT * FROM TABLE1 WHERE STATUSID = 1 OR STATUSID = 2
Is the easiest for the engine to optimize.

Union different tables with differents columns and data

My problem is that I have 4 differents SELECT with
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
I want that the results appear together whith the respective names like:
regular rptmm new rptss
10 5 2 6
Firstly, I'd suggest not to use Count()*. There are many answers on this site explaining why so I am not going to repeat it.
Instead, I'd suggest you to use a query like this:
SELECT (SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 1) AS 'Regular',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 0) AS 'rptmm',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 0) AS 'New',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 1) AS 'rptss'
Hope this helps!!!
Just put UNION ALL between your four statements you will get four rows with each count on its own row. However, you will lose the column name. You could also use join to get one row with four columnes. Just put the keyword join between each sql statement.
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
JOIN
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
JOIN
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
JOIN
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
You could create a temp table to hold all of this data for you: Replace Name1, Name2, Name3,Name4 with whatever you want to call them. These will be the column headers.
CREATE TABLE #Temp(
NAME1 INT
,NAME2 INT
,NAME3 INT
,NAME4 INT
)
INSERT INTO #Temp
(NAME1)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 1
INSERT INTO #Temp
(NAME2)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 0
INSERT INTO #Temp
(NAME3)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 0
INSERT INTO #Temp
(NAME4)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 1*
SELECT * FROM #Temp

SQL Implementing 'IN' operator with 'OR'

I am working on a legacy system which has a custom java implementation for generating SQL queries. That doesn't support 'IN' operation.
To implement 'IN' I have written something like
SELECT * from Q
WHERE IS_HIDDEN = 0 AND ID = 1
OR ID = 2 OR ID = 3 AND IS_DELETED = 0;
I know that the one like below would have been fine.
SELECT * from Q
WHERE IS_HIDDEN = 0 AND (ID = 1
OR ID = 2 OR ID = 3) AND IS_DELETED = 0 ;
Both these return the same result but I'm not too confident about SQL operator priorities. I had read that AND takes precedence
Is it safe to assume that both the SQL statemets are equivalent.
The actual query that I wanted to write is
SELECT * from Q
WHERE IS_HIDDEN = 0 AND ID IN(1, 2, 3) AND IS_DELETED = 0;
The DB in question is oracle 10g.
Update: The reason that this was working is because the oracle CBO rearranges the subclauses in the where clause.
No your queries are not the same
SELECT * from Q
WHERE IS_HIDDEN = 0 AND ID = 1
OR ID = 2 OR ID = 3 AND IS_DELETED = 0;
is like
SELECT * FROM Q WHERE IS_HIDDEN = 0 AND ID = 1
UNION
SELECT * FROM Q WHERE ID = 2
UNION
SELECT * FROM Q WHERE ID = 3 AND IS_DELETED = 0
when you use the parentheses for your ORs then you have the same like the IN-Clause
You can try it: SQLFiddle
You first query is equal to the IN. You should use that:
Your second query is like this:
SELECT * from Q
WHERE (IS_HIDDEN = 0 AND ID = 1) OR ID = 2 OR (ID = 3 AND IS_DELETED = 0);
If IS_HIDDEN is 1 or DELETED Is 1, but ID is 2, your query will still give you records. Try it..

SQL - "IF" in Where Clause

I'm trying to write a stored procedure that will have 6 bit value flags as parameters and a couple of other values.
The pseudo sql I want to write is something like:
SELECT *
FROM theTable
WHERE
IF #flagA = 1 THEN theTable.A = 1
IF #flagB = 1 THEN theTable.B = 1
IF #flagC = 1 THEN theTable.CValue = #cValue
etc
Any ideas how I can do this in SQL or am I best reverting to building the SQL in C# (where this SP will be called from)?
SELECT *
FROM theTable
WHERE
(#flagA = 0 or (#flagA = 1 AND theTable.A = 1 ))
and (#flagB = 0 or (#flagB = 1 AND theTable.B = 1 ))
and (#flagC = 0 or (#flagC = 1 AND theTable.CValue = #cValue ))
Note: I am assuming your bit flags are non-nullable. If that is not the case, you will need to use ISNULL.