Microsoft SQL query multiple condition - sql

I have an Attributes table which has a set of attributes identified by a unique number and then followed by their description - An example schema is
ID - AttributeName
with some sample data below
1 = FirstName
2 = LastName
3 = Phone
I then have an employees table which for the sake of simplicity has the following schema
ID - PersonID
AttribueID - INT Foreign key to the above attributes table
I need to create a stored proc that given a condition will return records based on one of the following conditions
If I pass in a 1 to the stored procedure the proc should return all records from the Person table who match the attribute ID 1 (First name)
If I pass in a 2 to the stored procedure the proc should return all records from the Person table who * DO NOT * match the attribute ID 1 (First name)
If I pass in a 3 to the stored procedure the proc should return all records from the Person table
I could do the following but feel it is not the best way this could be performed
DECLARE #IntID INT = 1 -- Set as 1 just for exmple
IF #IntID =1
BEGIN
SELECT * FROM Person where AttributeID IN (SELECT ID from Attributes Where ID =1) -- match on attribute 1
END
ELSE IF #IntID = 2
BEGIN
SELECT * FROM Person where AttributeID NOT IN (SELECT ID from Attributes Where ID =1) -- do not match on attribute 1
END
ELSE
BEGIN
SELECT * FROM Person where AttributeID IN (SELECT ID from Attributes) -- return match on all attributes
END
The above example has an extremely simple SELECT statement - in the real SQL there is a much larger set
Thanks in advance

If you don't wanna use dynamic sql then you may try this. And your query is too simple that for performance optimization, you may look to the table indexes for that.
DECLARE #IntID INT = 1 -- Set as 1 just for exmple
IF #IntID = 1 OR #IntID = 2
BEGIN
SELECT A.*
FROM Person A
LEFT JOIN Attributes B ON A.AttributeID = B.ID AND B.ID = 1
WHERE
A.AttributeID IS CASE #IntID WHEN 1 THEN NOT NULL WHEN 2 THEN NULL END
END
ELSE
BEGIN
SELECT A.*
FROM Person A
INNER JOIN Attributes B ON A.AttributeID = B.ID
END

Related

Delete rows from multiple tables with foreign keys

I have three tables
userTable with following rows Id, FirstName, LastName, Email
Product A with following rows Id, UserId(FK), startDate
Product D with following rows Id, UserId(FK), startDate
I want to delete rows from three tables with particular UserId.
What I want to achieve -
Find the id given email (select id from userTable where Email = 'abc.com') - got back id - 3
Delete from Product A where id = 3
Delete from Product D where id = 3
Delete from userTable where id = 3
I want to create a script.
Any help is appreciated or learning reference would be great.
Declare a variable and save the id to that variable. Use that Id for the delete query.
DECLARE #Id INT;
SELECT #Id=id
FROM userTable
WHERE Email = 'abc.com'
DELETE FROM Product A WHERE id = #Id
DELETE FROM Product D WHERE id = #Id
DELETE FROM userTable WHERE id = #Id
But I guess in your case you have UserId as the FK so you should be trying this:
DELETE FROM Product A WHERE UserId= #Id
DELETE FROM Product D WHERE UserId= #Id
DELETE FROM userTable WHERE id = #Id
Note: If you want to do the same thing what's there in question, go for 1st one. If you want to delete the relevant user records from A and D table then go for the 2nd method where you are deleting the records using the FK.
From what I can gather from your question you want something like this:
DELETE FROM
userTable,
ProductA,
ProductB
WHERE
userTable.Id = (select Id from userTable where Email like 'abc.com') AND
userTable.Id = ProductA.Id AND
userTable.Id = ProductB.Id;
And the Email in the subquery in the WHERE clause would be your input parameter
DISCLAIMER: From a Sybase/SQL Anywhere background, this would be possible, I'm not sure if it could be done in SQL-server.

How to join three tables with a NOT IN CLAUSE

Scenario ... A STORE gets a LIST. The 'LIST' basically is a collection of SKUs that the store stocks that needs to be counted.
When a store starts counting the SKUs from a given List assigned to it, the information is saved in another table called 'StoreCycles' which records the ListId, StoreName and the Dates the counting started and completed.
These are my tables.
Table 1. Table with 'Lists' which have a primary key 'ListId'
ListId ListName
1 abc
2 def
3 ghi
Table 2. 'Stores' -- Each list from the above table ('Lists' Table) is assigned to one or more stores.
The ListId in the 'Stores' Table is the primary key of the 'Lists' tabel. The Listid and LineId together make up the foreign key.
ListId LineId StoreName
1 1 StoreA
1 2 StoreD
2 1 StoreB
2 2 StoreC
2 3 StoreA
3 1 StoreA
Table 3. 'StoreCycles' -- that saves when the list assigned to a store was started counting and when it was completed.
ListId StoreName StartDate CompleteDate
1 StoreA 2016-7-22 2016-7-22
2 StoreA 2016-7-22
2 StoreC 2016-7-22
At any time I want to pull up those list names that have not been completed , i.e they have a null complete date.
This is my query:
Select T0.ListId,
T0.ListNaame ,
T2.StartDate
From Lists T0
JOIN Stores T1 On T0.ListId = T1.ListId
LEFT JOIN StoreCycles T2 ON T0.ListId = T2.ListId
WHERE T1.StoreName = 'StoreA'
AND T0.ListId NOT IN (SELECT ListId FROM StoreCycles WHERE CompleteDate IS NOT NULL)
RESULT SHOULD BE >>
ListId ListName StartDate
2 def 2016-7-22
3 ghi NULL
BUT The result that I get is this
ListId ListName StartDate
2 def NULL
2 def NULL
3 ghi NULL
Just passing by and dumping SQL.
Go on, nothing to see.
There is no bug hunt going on here.
declare #Lists table (ListId int primary key, ListName varchar(20));
insert into #lists values (1,'abc'),(2,'def'),(3,'ghi');
declare #Stores table (ListId int, LineId int, StoreName varchar(20));
insert into #Stores values
(1,1,'StoreA'),
(1,2,'StoreD'),
(2,1,'StoreB'),
(2,2,'StoreC'),
(2,3,'StoreA'),
(3,1,'StoreA');
declare #StoreCycles table (ListId int, StoreName varchar(20), StartDate date, CompleteDate date);
insert into #StoreCycles values
(1,'StoreA','2016-7-22','2016-7-22'),
(2,'StoreA','2016-7-22',null),
(2,'StoreC','2016-7-22',null);
SELECT
L.ListId,
L.ListName,
SC.StartDate
FROM #Stores S
JOIN #Lists L On (S.ListId = L.ListId)
LEFT JOIN #StoreCycles SC ON (S.ListId = SC.ListId AND S.StoreName = SC.StoreName)
WHERE S.StoreName = 'StoreA'
AND SC.CompleteDate IS NULL;
Select
l.ListId
,l.ListNaame
,sc.StartDate
From
Lists l
JOIN Stores s
ON l.ListId = s.ListId
AND s.StoreName = 'StoreA'
LEFT JOIN StoreCycles sc
ON s.ListId = sc.ListId
AND s.LineId = sc.LineId
WHERE
sc.CompleteDate IS NULL
You are already doing joins if you build them correctly you will not need a select or not in in your where clause. Also your relationship for StoreCycles seems to be wrong because you are trying to go straight from Lists to StoreCycles but Stores is the intermediary table.
Also just a thought why not use table aliases that will help you know what table you are referring to rather than t0, t1, t2 such as l, s, sc....
Maybe another way to look at it is to return all rows where either the StartDate is NULL (no records) or the CompleteDate is NULL (incomplete records). Also, if the foreign key is using 2 columns you probably want to use both columns in the JOIN.
SELECT T0.ListId,
T0.ListName,
T2.StartDate
FROM Lists T0
JOIN Stores T1
ON T1.ListId = T0.ListId
LEFT JOIN StoreCycles T2
ON T2.ListId = T1.ListId
AND T2.LineId = T1.LineId
WHERE T1.StoreName = 'StoreA'
AND (T2.CompleteDate IS NULL OR T2.StartDate IS NULL)

How to loop records table row by row in SQL Server?

Below are my tables :
Table:
ID Name category
--------------------
1 test 1
2 test 2
3 test1 3
4 test1 4
Category:
ID Name
------------
1 simple
2 complex
3 ordinory
4 ex-ordinory
In my table have 'Name' column. Each name has a category.
I need to fetch all names with categories wise.
select *
from table
inner join category ca on ca.id = table.category
where name = test
and category = 1
This query will return only name = test with category = 1 records
But I need to fetch all the names with their categories.
I am thinking to loop all the records row by row. Please suggest possible way to do this operation.
Is this what you're looking for?
CODE
CREATE TABLE TABLE_NAME (ID INT IDENTITY, NAME VARCHAR(25), CATEGORY INT)
INSERT INTO TABLE_NAME
VALUES ('test',1),('test',2),('test1',3),('test1',4)
CREATE TABLE CATEGORY (ID INT IDENTITY, NAME VARCHAR(25))
INSERT INTO CATEGORY
VALUES ('Simple'),('Complex'),('Ordinary'),('Ex-Ordinary')
SELECT DISTINCT
T.NAME
,C.NAME
FROM TABLE_NAME T
JOIN CATEGORY C
ON C.ID = T.CATEGORY
RESULT
TABLE_NAME CATEGORY_NAME
test Complex
test Simple
test1 Ex-Ordinary
test1 Ordinary

T-SQL Case statement where value is derived from joining tables

I have the following simple query (sql server 2012)
SELECT T.[taskId], T.[sectionId], T.[DateAdded]
FROM [TASK] AS T
WHERE (T.[deleted] = 0)
ORDER BY T.[DateAdded]
What I would like to do is create a computed column called type, which will be 1 if SectionId is null. If not null this will contain a foreign key for a table called Organisation. Organisation has a column called type. If the type of the joined row in organisation is 6 then my computed type value should be 2, else it will be 3.
I'm guessing a CASE would be ideal for this but I', not exactly sure how to go about it.
To project a derived column, add a join to your organisation table and derive the new column based on the various values:
SELECT T.[taskId], T.[sectionId], T.[DateAdded],
CASE
WHEN SectionId IS NULL THEN 1
WHEN o.[type] = 6 THEN 2
ELSE 3
END AS [type]
FROM [TASK] AS T
-- Applicable join condition goes here ...
LEFT OUTER JOIN Organisation o ON t.TaskID = o.TaskID
WHERE (T.[deleted] = 0)
ORDER BY T.[DateAdded]
If you **literally** want a computed column, it will look something like this:
ALTER TABLE TASK ADD [Type] AS
CASE
WHEN SectionId IS NULL THEN 1
WHEN (SELECT [type] FROM Organisation WHERE ... JOIN KEY) = 6 THEN 2
ELSE 3
END;

Subtract counts returned from two tables using tsql

I have two tables called A and B.
Table A contains request details such as
request_id, company_id, and Customer_id.
Table B contains feedback data such as feedback_id, company_id, status_ind,customer_id, score_total.
I need to get the count of rows of table B which has corresponding company_id with table A where the status_ind is 1 and subtract from the count of table A.
I'm not sure what you're asking but
declare #countA integer = (select count(*) from A)
declare #countB integer =
(select count(*) from B where
exists(select * from A where A.company_id = B.company_id AND A.status_ind = 1)
declare #difference integer = #countA - #countB
you have to use a sql stored procedure or function.
Seems like your problem can be rephrased like this: count rows of A that have no matches with the status_ind = 1 rows of B.
Well, just use an anti-join, like this, for instance:
SELECT COUNT(*)
FROM A
LEFT JOIN B ON A.company_id = B.company_id AND B.status_ind = 1
WHERE B.company_id IS NULL
I am also not sure. But i understood it like this:
SELECT COUNT(*) FROM A WHERE company_id NOT IN (SELECT company_id FROM B WHERE status_ind = 1)
I edited it, i thought first that status_ind is in table A not in B