SQL Query For Counting Sequence of Days Based on a Value - sql

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

Related

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;

Remove and Identify Duplicate Records in SQL

I have some sample records below that I need to use the CASE WHEN statement to remove and identify the duplicate records in SQL.
Quantity Values Desc event ID
1 5 Blue 12550 577
1 5 bluee 12550 525
2 10 blu 12550 535
i would like to use a case statement to show the duplicate indicators such as:
Dup_Quantity Dup_Value Dup_Desc Quantity Values Desc event ID
Y Y N 1 5 Blue 12550 577
Y Y N 1 5 Bluee 12550 525
however, after using this script, the result still shows as:
Dup_Quantity Dup_Value Dup_Desc Quantity Values Desc event ID
Y Y N 1 5 Blue 12550 577
Y Y N 1 5 Bluee 12550 525
Y N N 2 10 Blu 12550 535
SELECT DISTINCT
CASE WHEN a.Quantity = b.Quantity THEN 'Y' ELSE 'N' END AS "Dup_Quantity",
CASE WHEN a.Values = b.Values THEN 'Y' ELSE 'N' END AS "Dup_Value",
CASE WHEN a.Desc = b.Desc THEN 'Y' ELSE 'N' END AS "Dup_Desc"
FROM Table1 a
INNER JOIN Table1 b ON a.event = b.event
WHERE (a.Quantity = b.Quantity OR a.Values = b.Values OR a.Desc = b.Desc)
AND a.ID <> b.ID
Basically, record with ID 535 stills shows up in the result. Would someone Please give me some pointers?
SQL Fiddle
MS SQL Server 2012 Schema Setup:
CREATE TABLE Table1
([Quantity] int, [Values] int, [Desc] varchar(5), [event] int, [ID] int)
;
INSERT INTO Table1
([Quantity], [Values], [Desc], [event], [ID])
VALUES
(1, 5, 'Blue', 12550, 577),
(1, 5, 'bluee', 12550, 525),
(2, 10, 'blu', 12550, 535)
;
Query 1:
SELECT
CASE WHEN (SELECT COUNT(*)
FROM Table1 t2
WHERE t1.Quantity = t2.Quantity AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
THEN 'Y' ELSE 'N' END AS Dup_Quantity,
CASE WHEN (SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Values" = t2."Values" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
THEN 'Y' ELSE 'N' END AS Dup_Value,
CASE WHEN (SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Desc" = t2."Desc" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
THEN 'Y' ELSE 'N' END AS Dup_Desc,
*
FROM Table1 t1
WHERE
(SELECT COUNT(*)
FROM Table1 t2
WHERE t1.Quantity = t2.Quantity AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
OR
(SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Values" = t2."Values" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
OR
(SELECT COUNT(*)
FROM Table1 t2
WHERE t1."Desc" = t2."Desc" AND
t1.ID <> t2.ID AND t1.event = t2.event) > 0
Results:
| DUP_QUANTITY | DUP_VALUE | DUP_DESC | QUANTITY | VALUES | DESC | EVENT | ID |
|--------------|-----------|----------|----------|--------|-------|-------|-----|
| Y | Y | N | 1 | 5 | Blue | 12550 | 577 |
| Y | Y | N | 1 | 5 | bluee | 12550 | 525 |
Your query returns:
Dup_Quantity Dup_Value Dup_Desc
Y Y N
However I don't get what you want to do here, the correct version of it is:
SELECT
CASE WHEN a."Quantity" = b."Quantity" THEN 'Y' ELSE 'N' END AS "Dup_Quantity",
CASE WHEN a."Values" = b."Values" THEN 'Y' ELSE 'N' END AS "Dup_Value",
CASE WHEN a."Desc" = b."Desc" THEN 'Y' ELSE 'N' END AS "Dup_Desc",
a.*
FROM Table1 a
INNER JOIN Table1 b ON b.event = a.event
WHERE (a."Quantity" = b."Quantity" OR a."Values" = b."Values" OR a."Desc" = b."Desc")
AND a.ID <> b.ID
If you want to get duplicated rows in terms of Quantity, Values and Desc:
SELECT
a.*
FROM Table1 a
INNER JOIN Table1 b ON b.event = a.event
WHERE (a."Quantity" = b."Quantity" AND a."Values" = b."Values" AND a."Desc" = b."Desc")
AND a.ID <> b.ID

Join itself quest

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

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