Join itself quest - sql

I have table like this:
ID DADOS TIPO
1 UM 1
2 DOIS 1
3 TRES 1
4 QUATRO 1
5 CINCO 1
1 SEIS 2
I need to make a select that return this:
t1.id t1.dados t2.dados
1 Um Seis
2 Dois Null
3 Tres Null
4 Quatro Null
5 Cinco Null
I tried in this form:
SELECT T1.ID, T1.DADOS, T2.DADOS
FROM Tabela1 as T1 LEFT JOIN Tabela1 AS T2 ON T1.ID = T2.ID
WHERE T1.TIPO = 1 AND T2.TIPO = 2
But the result is this:
ID T1.DADOS T2.DADOS
1 UM SEIS
What I am doing wrong?

use this code for join table itself :
SELECT T1.ID, T1.DADOS, T2.DADOS
FROM Tabela1 as T1 LEFT JOIN Tabela1 AS T2 ON T1.ID = T2.ID
And T1.TIPO = 1 AND T2.TIPO = 2
also you can use this code :
SELECT T1.ID, T1.DADOS, T2.DADOS
FROM
( select * from Tabela1 T_1
where T_1.TIPO = 1) as T1
LEFT JOIN
(select * from Tabela1 T_2
Where T_2.TIPO = 2) AS T2 ON T1.ID = T2.ID

By using the clause WHERE T1.TIPO = 1 AND T2.TIPO = 2, you require that a matching record are found in T2, and thus in reality you are turning the left join into an inner join.
In order to include the records from T1 that have no matching record in T2, you can change the where clause to either
WHERE T1.TIPO = 1 AND (T2.TIPO IS NULL OR T2.TIPO = 2)
or
WHERE T1.TIPO = 1 AND T2.TIPO <> 1

This will do the work
SELECT T1.ID, T1.DADOS as T1Dados, T2.DADOS as T2Dados
FROM Tabela1 T1
left JOIN Tabela1 T2
ON T1.ID = T2.ID
and T1.TIPO = 1 and T2.TIPO = 2
See a demo here http://sqlfiddle.com/#!2/c7066/6

Related

How to randomly update a column if the number of records between the 2 join tables are not equal in Postgres sql

Table 1(5 records):
id
name
date
units
1
abc
3/16/2021
1
abc
3/17/2021
1
abc
3/18/2021
1
abc
3/19/2021
1
abc
3/20/2021
Table 2(3 records):
id
name
startdate
enddate
units
1
abc
3/16/2021
03/23/2021
2
1
abc
3/16/2021
03/23/2021
2
1
abc
3/16/2021
03/23/2021
2
Below is the join condition:
select * from Table1 a right join Table2 b on
(a.id = b.id) and (a.name = b.name) and (a.date between b.startdate and b.enddate)
I am trying to update the units columns in Table 1 from Table 2. My requirement is since there are 3 records in Table 2, only 3 records in Table 1 should be updated based on the above join condition. It can be random. But the number of records updated should not go above 3.
I tried doing this.
with e as
(select *,
row_number() over(partition by a.id
order by id) as rn
from Table1 a right join Table 2 b on (a.id = b.id) and (a.name = b.name) and (a.date between b.startdate and b.enddate)
)
update table1
set units = e.units
from e
where e.rn = 1
However, in this case all 5 records get updated. How do I resolve this? Any help is appreciated. Thank you.
Join the tables together. Then choose one row from from table2 for each row in table1 and do the update:
update table1 t1
set t1.units = t2.units
from (select distinct on (t1.id, t1.name, t1.date) t1.*, t2.units
from table1 t1 join
table2 t2
on t2.id = t1.id and t2.name = t1.name and
t1.date between t2.startdate and t2.enddate
order by t1.id, t1.name, t1.date, random())
) tt1
where tt1.name = t1.name and
tt1.id = t1.id and
tt1.date = t1.date;

SQL Server Select ID from table 1 where all ID in table2 match criteria

Table1 Table2
requestID requestComplete requestID DocumnentNum DocumentComplete
1 0 1 ABC 1
2 1 1 DEF 1
3 0 1 GHI 1
4 0 2 XXX 1
5 1 3 YYY 0
My question is this: how do I find requestID's from table one where requestComplete = 0 and all the documents for that requestID in table2 have documentCompleted = 1?
select t1.requestID
from table1 t1
join table2 t2 on t1.requestID = t2.requestID
where t1.requestComplete = 0
group by t1.requestID
having sum(case when documentCompleted <> 1 then 1 else 0 end) = 0
SELECT t1.requestID
FROM Table1 t1
WHERE NOT EXISTS (
SELECT *
FROM Table2 t2
WHERE t1.requestID = t2.requestID
AND t2.DocumentComplete = 0
) AND t1.requestComplete = 1
should work like:
SELECT T1.*
FROM Table1 T1
WHERE T1.requestComplete = 0
AND NOT EXISTS (SELECT 1
FROM Table2 T2
WHERE T2.requestID = T1.requestID
AND T2.DocumentComplete != 1)
If T2.DocumentComplete is of a numeric datatype you can do something like this.
SELECT t1.RequestID, t1.RequestComplete, t2.MinDoc
FROM Table1 t1
JOIN (SELECT t2.RequestID, MIN(t2.DocumentComplete) AS MinDoc
FROM Table2 t2
GROUP BY t2.RequestID
HAVING MIN(t2.DocumentComplete) = 1) t2 ON t1.RequestID = t2.Requestid
WHERE t1.RequestComplete = 0
If it is not then you could just convert the t2.documentcomplete to INT. It would look like this.
SELECT t1.RequestID, t1.RequestComplete, t2.MinDoc
FROM Table1 t1
JOIN (SELECT t2.RequestID, MIN(CONVERT(INT,t2.DocumentComplete)) AS MinDoc
FROM Table2 t2
GROUP BY t2.RequestID
HAVING MIN(CONVERT(INT,t2.DocumentComplete)) = 1) t2 ON t1.RequestID =
t2.Requestid
WHERE t1.RequestComplete = 0

Waterfall join conditions

I have two tables similar to:
Table 1 --unique ID's
ID Date
1 3/8/2017
2 3/8/2017
3 3/8/2017
Table 2
ID Date SourceID
1 3/8/2017 1
1 3/8/2017 2
1 3/8/2017 3
2 3/8/2017 2
3 3/8/2017 1
3 3/8/2017 3
And I want to write a query that has a result like:
Result
ID SourceID
1 2
2 2
3 1
Where the source ID ordering should be 2, 1, 3
I have:
select Table1.ID
, COALESCE(Join1.SourceID, Join2.SourceID, Join3.SourceID) as SourceID
from Table1
left outer join Table2 Join1
on Table1.date = Join1.date
and Table1.ID = Join1.ID
and Join1.SourceID = 2
left outer join Table2 Join2
on Table1.date = Join2.date
and Table1.ID = Join2.ID
and Join2.SourceID = 1
and Join1.SourceID is null
left outer join Table2 Join3
on Table1.date = Join3.date
and Table1.ID = Join3.ID
and Join3.SourceID = 3
and Join1.SourceID is null
and Join2.SourceID is null
But this currently just keeps the records where sourceid = 2 and does not add in the other sourceid's.
Thanks in advance for any help. Let me know if you need any clarification. Using SQL-Server. I only need a few and fixed amount of sources so I am avoiding using a cursor.
This is a prioritization query. I would do it using outer apply:
select t1.*, t2.sourceId
from table1 t1 outer apply
(select top 1 t2.*
from table2 t2
where t2.id = t1.id and t2.date = t1.date
order by (case t2.sourceid when 2 then 1 when 1 then 2 when 3 then 3 end)
) t2;
Note: For readability, you can simplify the order by to:
order by charindex(cast(t2.sourceId as varchar(255)), '2,1,3')
If you are uncomfortable with outer apply, you can do the same thing with a single join:
select t1.*, t2.sourceId
from table1 t1 join
(select t2.*,
row_number() over (partition by id, date
order by (case t2.sourceid when 2 then 1 when 1 then 2 when 3 then 3 end)
) as seqnum
from table2 t2
) t2
on t2.id = t1.id and t2.date = t1.date and t2.seqnum = 1;

SQL Query For Counting Sequence of Days Based on a Value

I have table that has id, timestamp and control value.
I need query for ids which has control value 0 for 4 days or more in sequence
TimeS ID Kontrol
2012-06-18 5457554F-E9A5-4312-8BA3-424B2333D0B7 1
2012-06-14 3FC4AC80-7D94-496A-92D0-22350CA3CEA9 1
2012-06-14 FE3C1872-0F13-48CC-A6C9-BBE0EAB07B9D 0
2012-06-13 FE3C1872-0F13-48CC-A6C9-BBE0EAB07B9D 0
2012-06-12 FE3C1872-0F13-48CC-A6C9-BBE0EAB07B9D 0
2012-06-11 FE3C1872-0F13-48CC-A6C9-BBE0EAB07B9D 0
It should return FE3C1872-0F13-48CC-A6C9-BBE0EAB07B9 for example.
Try this:
SELECT t1.id
FROM tableName t1
WHERE t1.kontrol = 0
AND EXISTS (SELECT 1
FROM tableName t2
WHERE t2.id = t1.id
AND t2.kontrol = 0
AND t2.timeS = t1.timeS + 1
AND EXISTS (SELECT 1
FROM tableName t3
WHERE t3.id = t2.id
AND t3.kontrol = 0
AND t3.timeS = t2.timeS + 1
AND EXISTS (SELECT 1
FROM tableName t4
WHERE t4.id = t3.id
AND t4.kontrol = 0
AND t4.timeS = t3.timeS + 1)))
SELECT DISTINCT t1.id
FROM table t1
INNER JOIN
table t2 ON t2.TimeS+1 days=t1.TimeS
INNER JOIN
table t3 ON t3.TimeS+2 days=t1.TimeS
INNER JOIN
table t4 ON t4.TimeS+3 days=t1.TimeS
WHERE t1.Control = 0 AND
t2.Control = 0 AND
t3.Control = 0 AND
t4.Control = 0
Try this query
select
id,
count(distinct TimeS)
from
table1
where
kontrol=0
group by
id
having
count(distinct TimeS) >= 4;
FIDDLE

SQL: 3 self-joins and then join them together

I have 2 tables to join in a specific way. I think my query is right, but not sure.
select t1.userID, t3.Answer Unit, t5.Answer Demo
FROM
table1 t1
inner join (select * from table2) t3 ON t1.userID = t3.userID
inner join (select * from table2) t5 ON t1.userID = t5.userID
where
NOT EXISTS (SELECT * FROM table1 t2 WHERE t2.userID = t1.userID AND t2.date > t1.date)
and NOT EXISTS (SELECT * FROM table2 t4 WHERE t4.userID = t3.userID and t4.counter > t3.counter)
and NOT EXISTS (SELECT * FROM table2 t6 WHERE t6.userID = t5.userID and t6.counter > t5.counter)
and t1.date_submitted >'1/1/2009'
and t3.question = Unit
and t5.question = Demo
order by
t1.userID
From table1 I want distinct userID where date > 1/1/2009
table1
userID Date
1 1/2/2009
1 1/2/2009
2 1/2/2009
3 1/2/2009
4 1/1/2008
So The result I want from table1 should be this:
userID
1
2
3
I then want to join this on userID with table2, which looks like this:
table2
userID question answer counter
1 Unit A 1
1 Demo x 1
1 Prod 100 1
2 Unit B 1
2 Demo Y 1
3 Prod 100 1
4 Unit A 1
1 Unit B 2
1 Demo x 2
1 Prod 100 2
2 Unit B 2
2 Demo Z 2
3 Prod 100 2
4 Unit A 2
I want to join table1 with table2 with this result:
userID Unit Demo
1 B X
2 B Z
In other words,
select distinct userID from table2 where question = Unit for the highest counter
and then
select distinct userID from table2 where question = Demo for the highest counter.
I think what I've done is 3 self-joins then joined those 3 together.
Do you think it's right?
SELECT du.userID, unit.answer, demo.answer
FROM (
SELECT DISTINCT userID
FROM table1
WHERE date > '1/1/2009'
) du
LEFT JOIN
table2 unit
ON (userID, question, counter) IN
(
SELECT du.userID, 'Unit', MAX(counter)
FROM table2 td
WHERE userID = du.userID
AND question = 'Unit'
)
LEFT JOIN
table2 demo
ON (userID, question, counter) IN
(
SELECT du.userID, 'Demo', MAX(counter)
FROM table2 td
WHERE userID = du.userID
AND question = 'Demo'
)
Having an index on table2 (userID, question, counter) will greatly improve this query.
Since you mentioned SQL Server 2005, the following will be easier and more efficient:
SELECT du.userID,
(
SELECT TOP 1 answer
FROM table2 ti
WHERE ti.user = du.userID
AND ti.question = 'Unit'
ORDER BY
counter DESC
) AS unit_answer,
(
SELECT TOP 1 answer
FROM table2 ti
WHERE ti.user = du.userID
AND ti.question = 'Demo'
ORDER BY
counter DESC
) AS demo_answer
FROM (
SELECT DISTINCT userID
WHERE date > '1/1/2009'
FROM table1
) du
To aggregate:
SELECT answer, COUNT(*)
FROM (
SELECT DISTINCT userID
FROM table1
WHERE date > '1/1/2009'
) du
JOIN table2 t2
ON t2.userID = du.userID
AND t2.question = 'Unit'
GROUP BY
answer