return true if all the the records of first table exists in second table - sql

i have two table:
declare #t1 table (id int)
declare #t2 table (id int)
insert into #t1
select 1 union select 3 union select 7
insert into #t2
select 1 union select 3 union select 7 union select 9 union select 4
select count(*) from #t1 t inner join #t2 t1 on t.id = t1.id
i get the result for above query as 3. i need true or false if all the records in t1 exists in t2.
this is a simplified example of the real table structure. the real tables may have millions of records, so please let me know some optimized way of doing it

SELECT CASE
WHEN EXISTS (SELECT id
FROM #t1
EXCEPT
SELECT id
FROM #t2) THEN 0
ELSE 1
END

declare #t1 table (id int)
declare #t2 table (id int)
insert into #t1
select 1 union select 3 union select 7
insert into #t2
select 1 union select 3 union select 7 union select 9 union select 4
if exists(
select id from #t2
except
select id from #t1
) print 'false'
else print 'all the records in t1 exists in t2'

Using exists (probably, it would be more efficient):
select
case
when not exists (select 1
from #t1 t1
where not exists(select 1 from #t2 t2 where t2.id = t1.id))
then cast(1 as bit)
else cast(0 as bit)
end

SELECT (CASE WHEN
(SELECT COUNT(*) from t1 where
not id IN (select id from t2)) = 0 THEN
convert(bit, 1)
ELSE convert(bit, 0) END)

Comparing count of matched rows to the total rows in #t1 may be more efficient. Sometimes you just need to try multiple methods and look at query plans to see which one works best in your situation. You'll need some test tables with a similar amount of data and proper indexes and such.
declare #t1 table (id int)
declare #t2 table (id int)
insert into #t1
select 1 union select 3 union select 7
insert into #t2
select 1 union select 3 union select 7 union select 9 union select 4
select case
when (select count(*) from #t1 t join #t2 t1 on t.id = t1.id) =
(select count(*) from #t1) then 1 else 0
end as rows_match

Related

conditional union multiple tables

This is based on union tables on value
declare #t1 table (val int,datatype1 int,datatype2 int ,datatype3 int)
declare #t2 table (val int,datatype1 int ,datatype2 int ,datatype3 int )
declare #t3 table (val int,datatype1 int ,datatype2 int ,datatype3 int )
insert into #t1 values (10,1,0,0),(31,1,0,0),(20,1,0,0)
insert into #t2 values (31,0,1,0),(4,0,1,0)
insert into #t3 values (31,0,0,1),(5,0,0,1);
Below is the changes in requirement(case):
1. need to union #t1,#t2 & #t3
(if same value exist #t1 & #t2 multiple rows and #t2 & t3 only 1 row)
2. if any duplicate value (there is no chance dup in same table)
i) suppose 31 in #t1 , 31 in #t2 then multiple rows are allowed
ii) suppose 31 in #t2 & #t3 then only one records i.e #t3 updated to #t2
iii) if 31 in #t1 ,#t2,#t3 only 2 records i.e #t1,#t2 records with #t3 details updated to #t2 records
Now i) & iii) are working fine
select val,
max(datatype1) datatype1,
max(datatype2)datatype2,
max(datatype3)datatype3
from (
select 't1' AS tab_name, * from #t1
union all
select 't2' AS tab_name,* from #t2
union all
select 't3' AS tab_name,* from #t3
) as data
group by val, CASE WHEN tab_name in ('t2') THEN 1 END
order by val;
But Current Result showing multiple records for case 2 also any help
Expected Result:
Your question is very hard to follow. I'm a bit lost on the conditions, but this rather simple query returns the results that you specify:
select val,
max(datatype1) as datatype1,
max(datatype2) as datatype2,
max(datatype3) as datatype3,
max(datatype4) as datatype4
from (select 't1' AS tab_name, t1.* from t1
union all
select 't2' AS tab_name, t2.* from t2
union all
select 't3' AS tab_name, t3.* from t3
) data
group by val;
Here is a db<>fiddle.
I wonder if the culmination of all your results is a relatively simple aggregation.

Update statement with Where Not Exists

I am trying to do the following:
Set the status column to 1 when the row in the first table (variable) does not exist in the second one.
I tried this:
update #table1
set status=1
where NOT EXISTS (select top 1 1 from #table2 where #table1.foo=#table2.foo)
But this doesn't even compile, not recognizing #table1 in the Where statement.
Must declare the scalar variable "#table1".
Any clue about this?
Your approach is fine. You just need table aliases because the # is used to in SQL Server to represent variables (scalars or tables) and is hence problematic for aliases:
update t1
set status = 1
from #table1 t1
where not exists (select 1 from #table2 t2 where t2.foo = t1.foo);
Note that the top 1 is unnecessary in the subquery.
You can do this kind of thing by joining the two tables with a LEFT JOIN and checking the right side for NULL:
UPDATE t1
SET t1.status=1
FROM #table1 t1
LEFT JOIN #table2 t2
ON t1.foo = t2.foo
WHERE t2.foo IS NULL
The specific error you got is because you haven't got a statement declaring #table1 as a table variable, like DECLARE #table1 TABLE (foo int) for example. If table1 is not a variable, you don't need the #.
no need any top inside scaler query
update #table1
set status=1
where NOT EXISTS (select 1 from #table2 where #table1.foo=#table2.foo)
cause exists return boolean
you could use below query
update #table1
set status=1
where #table1.foo not in ( select foo from #table2 where foo is not null)
There are multiple ways - inner query with NOT IN and NOT EXISTS and JOIN query:
update tab1 set status = 1 where name not in (select name from tab2);
update tab1 set status = 1 where not exists (select 1 from tab2 where tab1.name=tab2.name);
update tab1 set status = 1 from tab1 left outer join tab2 on tab1.name = tab2.name where tab2.name is null;
Sample schema to run above queries;
create table tab1(name varchar(30), status int);
create table tab2(name varchar(30));
insert into tab1 values('a', 5);
insert into tab1 values('b', 6);
insert into tab1 values('c', 7);
insert into tab1 values('d', 8);
insert into tab2 values('a');
insert into tab2 values('d');
You have to declare table1 and table2 variables
DECLARE #table1 YOUR_TABLE1_NAME;
DECLARE #table2 YOUR_TABLE2_NAME;
update #table1
set status=1
where NOT EXISTS (select top 1 from #table2 where #table1.foo=#table2.foo)
You should use alias name for both table.
DECLARE #TABLE_1 TABLE (DEPT_NAME VARCHAR(50),DEP_ID INT)
INSERT INTO #TABLE_1(DEPT_NAME,DEP_ID)
SELECT 'IT',1 UNION ALL
SELECT 'HR',2 UNION ALL
SELECT 'ACCOUNT',3 UNION ALL
SELECT 'ADMIN',4 UNION ALL
SELECT 'SALES',5 UNION ALL
SELECT 'CEO',7
DECLARE #TABLE_2 TABLE (E_ID INT,EMP_NAME VARCHAR(50),DEP_ID INT)
INSERT INTO #TABLE_2(E_ID,EMP_NAME,DEP_ID)
SELECT 1,'JHON',1 UNION ALL
SELECT 2,'LITA',2 UNION ALL
SELECT 3,'MATT',1 UNION ALL
SELECT 4,'JEFF',1 UNION ALL
SELECT 5,'BROCK',2 UNION ALL
SELECT 6,'BOB',5 UNION ALL
SELECT 7,'SAM',4 UNION ALL
SELECT 8,'DAVID',3 UNION ALL
SELECT 9,'JACK',1 UNION ALL
SELECT 10,'GARY',4 UNION ALL
SELECT 11,'DONALD',6
SELECT * FROM #TABLE_1 A WHERE NOT EXISTS (SELECT DEP_ID FROM #TABLE_2 B WHERE A.DEP_ID=B.DEP_ID )

Unique Count - TSQL

CODE
CREATE TABLE #TEMP (ID INT, AVAIL BIT, FK INT, DT DATETIME);
INSERT INTO #TEMP (ID,AVAIL,FK,DT)
SELECT 1,1,1,GETDATE()
UNION ALL
SELECT 2,0,2,GETDATE()
UNION ALL
SELECT 3,1,3,GETDATE()
UNION ALL
SELECT 1,1,4,GETDATE()
UNION ALL
SELECT 4,0,5,GETDATE()
UNION ALL
SELECT 5,1,6,GETDATE();
CREATE TABLE #FK (FK INT, DT2 DATETIME)
INSERT INTO #FK (FK, DT2)
SELECT 1,NULL
UNION
SELECT 2,DATEADD(DAY,1,GETDATE())
UNION
SELECT 3,DATEADD(DAY,1,GETDATE())
UNION
SELECT 4,NULL
UNION
SELECT 5,NULL
UNION
SELECT 6,DATEADD(DAY,1,GETDATE())
UNION
SELECT 7,DATEADD(DAY,1,GETDATE())
SELECT
[TotalIds] = COUNT(DISTINCT ID)
,[TotalAvail] = SUM(CASE WHEN [AVAIL] = 1 THEN 1 ELSE 0 END)
,[DTDIFF] = SUM(DATEDIFF(DAY,T1.DT,F.DT2))
FROM #TEMP T1 INNER JOIN #FK F
ON T1.FK = F.FK;
DROP TABLE #TEMP;
DROP TABLE #FK;
OUTPUT
TotalIds TotalAvail DTDIFF
5 4 3
DESIRED OUTPUT
TotalIds TotalAvail DTDIFF
5 3 3
GOAL:
I want to get sum/count of UNIQUE IDs where [AVAIL] = 1.
I can do that by COUNT(DISTINCT ID) WHERE [AVAIL] = 1 BUT... I need to do that within this SUM since I'm querying other data within the same query.
Desired output = 3
(for ID 1, 3, and 5).
Updated with Current/Desired output.
Updated with more data.
You could change UNION ALL for UNION and remove the duplicates
But you mention otherValue, so maybe you need something like this
SELECT SUM(otherValue)
FROM (
SELECT DISTINCT ID, AVAIL, otherValue
FROM TEMP
WHERE [AVAIL] = 1
) T
CREATE TABLE #TEMP (ID INT, AVAIL BIT, FK INT, DT DATETIME);
INSERT INTO #TEMP (ID,AVAIL,FK,DT)
SELECT 1,1,1,GETDATE()
UNION ALL
SELECT 2,0,2,GETDATE()
UNION ALL
SELECT 3,1,3,GETDATE()
UNION ALL
SELECT 1,1,4,GETDATE()
UNION ALL
SELECT 4,0,5,GETDATE()
UNION ALL
SELECT 5,1,6,GETDATE();
CREATE TABLE #FK (FK INT, DT2 DATETIME)
INSERT INTO #FK (FK, DT2)
SELECT 1,NULL
UNION
SELECT 2,DATEADD(DAY,1,GETDATE())
UNION
SELECT 3,DATEADD(DAY,1,GETDATE())
UNION
SELECT 4,NULL
UNION
SELECT 5,NULL
UNION
SELECT 6,DATEADD(DAY,1,GETDATE())
UNION
SELECT 7,DATEADD(DAY,1,GETDATE())
SELECT
[TotalIds] = COUNT(DISTINCT ID)
,[TotalAvail] = COUNT(DISTINCT CASE WHEN [AVAIL] = 1 THEN ID ELSE NULL END)
,[DTDIFF] = SUM(DATEDIFF(DAY,T1.DT,F.DT2))
FROM #TEMP T1 INNER JOIN #FK F
ON T1.FK = F.FK;
DROP TABLE #TEMP;
DROP TABLE #FK;
Use the cte result for your further process.
;WITH CTE_Temp AS
(SELECT COUNT(DISTINCT ID) [TotalAvail]
FROM #TEMP
WHERE [Avail]=1)
SELECT [TotalAvail]
FROM CTE_Temp

SQL grouping by parent child

If I had this structure with the columns:
Primary_Key, Name, Parent_Primary_ID, DISPLAY_ORDER
1 Event NULL 1
2 News NULL 2
3 Event_List 1 1
4 Event_Detail 1 2
5 News_List 2 1
6 News_Details 2 2
how would you return data like:
1 Event
3 Event_List
4 Event_Detail
2 News
5 News_List
6 News_Detail
Thanks
Rob
If SQL Server 2005+
DECLARE #YourTable TABLE
(Primary_Key INT PRIMARY KEY,
Name VARCHAR(100),
Parent_Primary_ID INT NULL,
DISPLAY_ORDER INT)
INSERT INTO #YourTable
SELECT 1,'Event',NULL,1 UNION ALL
SELECT 2,'News',NULL,2 UNION ALL
SELECT 3,'Event_List',1,1 UNION ALL
SELECT 4,'Event_Detail',1,2 UNION ALL
SELECT 5,'News_List',2,1 UNION ALL
SELECT 6,'News_Details',2,2;
WITH Hierarchy
AS (SELECT *,
path = CAST(DISPLAY_ORDER AS VARCHAR(100))
FROM #YourTable
WHERE Parent_Primary_ID IS NULL
UNION ALL
SELECT y.Primary_Key,
y.Name,
y.Parent_Primary_ID,
y.DISPLAY_ORDER,
CAST(path + '.' + CAST(y.DISPLAY_ORDER AS VARCHAR) AS VARCHAR(100))
FROM #YourTable y
JOIN Hierarchy h
ON h.Primary_Key = y.Parent_Primary_ID)
SELECT Primary_Key,
Name
FROM Hierarchy
ORDER BY path
Try (asumming standardish sql is supported)
DECLARE #YourTable TABLE
(Primary_Key INT PRIMARY KEY,
Name VARCHAR(100),
Parent_Primary_ID INT NULL,
DISPLAY_ORDER INT)
INSERT INTO #YourTable
SELECT 1,'Event',NULL,1 UNION ALL
SELECT 2,'News',NULL,2 UNION ALL
SELECT 3,'Event_List',1,1 UNION ALL
SELECT 4,'Event_Detail',1,2 UNION ALL
SELECT 5,'News_List',2,1 UNION ALL
SELECT 6,'News_Details',2,2;
select
primary_key = t1.primary_key,
name = t1.name
from
#YourTable t1
left join #YourTable t2 on t1.parent_primary_id = t2.Primary_Key
order by
coalesce(t2.DISPLAY_ORDER,t1.DISPLAY_ORDER,0),
case
when t2.Primary_Key is null then 0
else t1.DISPLAY_ORDER
end
I don't see any grouping in your results. Unless you are trying to do something you aren't telling us I would use the query below:
SELECT Primary_Key, Name FROM YourTable
I don't see how you are ordering those results so I didn't try to order them.

Query: find rows that do not belong to a list of values

Lets consider I have a table 'Tab' which has a column 'Col'
The table 'Tab' has this data -
Col
1
2
3
4
5
If I have a set of values (2,3,6,7). I can query the values that are present in the table and the list by suing the query
Select Col from Tab where col IN (2,3,6,7)
But, if I want to return the values in the list that are not present in the table i.e. only (6,7) in this case. What query should I use?
The problem I believe is that your trying to find values from you in statement. What you need to do is turn your in statement into a table and then you can determine which values are different.
create table #temp
(
value int
)
insert into #temp values 1
insert into #temp values 2
insert into #temp values 3
insert into #temp values 4
select
id
from
#temp
where
not exists (select 1 from Tab where Col = id)
A better alternative would be to create a table-valued function to turn your comma-delimited string into a table. I don't have any code handy, but it should be easy to find on Google. In that case you would only need to use the syntax below.
select
id
from
dbo.SplitStringToTable('2,3,6,7')
where
not exists (select 1 from Tab where Col = id)
Hope this helps
A SQL Server 2008 method
SELECT N FROM (VALUES(2),(3),(6),(7)) AS D (N)
EXCEPT
Select Col from Tab
Or SQL Server 2005
DECLARE #Values XML
SET #Values =
'<r>
<v>2</v>
<v>3</v>
<v>6</v>
<v>7</v>
</r>'
SELECT
vals.item.value('.[1]', 'INT') AS Val
FROM #Values.nodes('/r/v') vals(item)
EXCEPT
Select Col from Tab
one way would be to use a temp table:
DECLARE #t1 TABLE (i INT)
INSERT #t1 VALUES(2)
INSERT #t1 VALUES(3)
INSERT #t1 VALUES(6)
INSERT #t1 VALUES(7)
SELECT i FROM #t1 WHERE i NOT IN (Select Col from Tab)
One method is
declare #table table(col int)
insert into #table
select 1 union all
select 2 union all
select 3 union all
select 4 union all
select 5
declare #t table(col int)
insert into #t
select 2 union all
select 3 union all
select 6 union all
select 7
select t1.col from #t as t1 left join #table as t2 on t1.col=t2.col
where t2.col is null
Do you have a [numbers] table in your database? (See Why should I consider using an auxiliary numbers table?)
SELECT
[Tab].*
FROM
[numbers]
LEFT JOIN [Tab]
ON [numbers].[num] = [Tab].[Col]
WHERE
[numbers].[num] IN (2, 3, 6, 7)
AND [Tab].[Col] IS NULL
I think there are many ways to achive this, here is one.
SELECT a.col
FROM
(SELECT 2 AS col UNION ALL SELECT 3 UNION ALL SELECT 6 UNION ALL SELECT 7) AS a
WHERE a.col NOT IN (SELECT col FROM Tab)
Late to the party...
SELECT
'2s' = SUM(CASE WHEN Tab.Col = 2 THEN 1 ELSE 0 END),
'3s' = SUM(CASE WHEN Tab.Col = 3 THEN 1 ELSE 0 END),
'6s' = SUM(CASE WHEN Tab.Col = 6 THEN 1 ELSE 0 END),
'7s' = SUM(CASE WHEN Tab.Col = 7 THEN 1 ELSE 0 END)
FROM
(SELECT 1 AS Col, 'Nums' = 1 UNION SELECT 2 AS Col,'Nums' = 1 UNION SELECT 3 AS Col, 'Nums' = 1 UNION SELECT 4 AS Col, 'Nums' = 1 UNION SELECT 5 AS Col, 'Nums' = 1 ) AS Tab
GROUP BY Tab.Nums
BTW, mine also gives counts of each, useful if you need it. Like if you were checking a product list against what you have in inventory. Though you can write a pivot for that better, just don't know how off the top of my head.