I want to find duplicate phones in TableC (batch 82) but phone is stored in TableD
I need to compare tablec against itself while getting the phone from tabled
Any ideas on how to go about this are appreciated?
SELECT *
FROM (SELECT d.phone,
d.id
FROM tablec c
JOIN tabled d
ON c.tableid = d.id
WHERE c.batch = 82) d
JOIN (SELECT d.phone,
d.id
FROM tablec c
JOIN tabled d
ON c.tableid = d.id
WHERE c.batch = 82) c
ON d.phone = c.phone
WHERE d.id < c.id
SELECT d.phone,
MIN(d.id) MINID, MAX(d.id) MAXID , COUNT(*) COUNT
FROM tablec c
JOIN tabled d
ON c.tableid = d.id
WHERE c.leadlistid = 81
GROUP BY d.phone
HAVING COUNT(*)> 1
SELECT
d.phone,
count(c.phone)
FROM
tableD d
LEFT JOIN tableC c
ON d.id = c.tableID
/* not sure what you mean by batch 82 -- maybe this: (?)
WHERE
c.batch = 82
*/
GROUP BY
d.phone
HAVING
count(c.phone) > 1
Related
I'm trying to rewrite a select from multiple tables into a series of joins. I thought my solution would be equivalent but it's not returning the same data. An ideas? Here's the code:
/* without joins:*/
SELECT
A.column3,
D.column6,
E.column2,
I.column2,
E.column3,
F.column1,
G.column2
FROM table1 A, table2 B, table3 C, table4 D, table5 E, table6 F, table7 G table8 H
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE
A.ID = C.ID
B.ID = C.ID
D.ID = B.ID
D.ID = E.ID
E.ID = F.ID
F.ID = G.ID
E.ID = H.ID
AND H.ISDELETED<>'T'
AND D.ISDELETED<> 'T'
/* Here's my attempt to turn it into at series of joins: */
SELECT
D.column3,
E.column6,
I.column2,
E.column2,
F.column3,
G.column1
FROM table1 A
JOIN table3 C ON A.ID = C.ID
JOIN table2 B ON B.ID = C.ID
JOIN table4 D ON D.ID = B.ID
JOIN table5 E ON D.ID = E.ID
JOIN table6 F ON E.ID = F.ID
JOIN table7 G ON F.ID = G.ID
JOIN table8 H ON E.ID = H.ID
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE G.ISDELETED<>'T'
AND E.ISDELETED<> 'T'
Change your query with the JOIN's to this and see if it matches up with your initial query:
SELECT
A.column3,
D.column6,
E.column2,
I.column2,
E.column3,
F.column1,
G.column2
FROM table1 A
INNER JOIN table2 B ON A.ID = C.ID
INNER JOIN table3 C ON B.ID = C.ID
INNER JOIN table4 D ON D.ID = B.ID
INNER JOIN table5 E ON D.ID = E.ID
INNER JOIN table6 F ON E.ID = F.ID
INNER JOIN table7 G ON F.ID = G.ID
INNER JOIN table8 H ON E.ID = H.ID
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE
AND H.ISDELETED<>'T'
AND D.ISDELETED<> 'T'
Your aliases do not match between the two queries which may throw off the results of the JOIN.
Also, in your first query your WHERE clause is:
AND table8.ISDELETED<>'T'
AND table4.ISDELETED<> 'T'
In your bottom query, your WHERE clause is:
AND table7.ISDELETED<>'T'
AND table5.ISDELETED<> 'T'
Which may also lead to difference results between the two.
I need to concatinate results from 2 tables without using UNION.
Ex : I have 4 tables a, b, c, d. see below snips:
Table a:
Table b:
Table c:
Table d:
I am concatinating a and d results using UNION ALL like below:
select a.id,a.seq,a.item,b.des,c.qty from a
left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
UNION ALL
select d.id,d.seq,d.item,d.des,c.qty from d
join c on d.id = c.id and d.seq = c.seq
My output:
But I need same result without using UNION ALL.
Is it possible if so HOW?
You can apply Full Outer join instead of Union which has its similarities to Union
SELECT a.id,a.seq,a.item,b.des,c.qty
FROM a left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
FULL OUTER JOIN
(
SELECT d.id,d.seq,d.item,d.des,c.qty
FROM d join c on d.id = c.id and d.seq = c.seq
)x ON a.id = x.id
You can replace union all with full join with a "false" condition and lots of COALESCE()s.
The logic looks like this:
SELECT COALESCE(abc.id, cd.id) as id,
COALESCE(abc.seq, cd.seq) as seq,
COALESCE(abc.item, cd.item) as item,
COALESCE(abc.des, cd.des) as eesc,
COALESCE(abc.qty, cd.qty) as qty
FROM (SELECT a.id, a.seq, a.item, b.des, c.qty
FROM a LEFT JOIN
b
ON a.item = b.item LEFT JOIN
c
ON a.id = c.id AND a.seq = c.seq
) abc FULL JOIN
(SELECT d.id, d.seq, d.item, d.des, c.qty
FROM d JOIN
c
ON d.id = c.id AND d.seq = c.seq
) dc
ON 1 = 0; -- never evaluates to true
There is a LEFT JOIN from table 'a' to table 'c' (on 'id' and 'seq' columns) in the upper query and INNER JOIN from table 'd' to table 'c' in the lower query. Therefore I think you could LEFT JOIN from table 'c' to table 'd' and it would produce the correct output.
select a.id,a.seq,a.item,b.des,c.qty
from a
left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
left join d on c.id = d.id and c.seq = d.seq;
If you want you can use INSERT INTO a (tmp) table and get the same result in a table.
I have complex join query ,
Select a.date, b.Name, d.description
FROM tableA as a
INNER JOIN (SELECT Name, MAX(Time) as lastSentTime FROM tableA
GROUP BY Name) b ON a.Name = omh.Name AND b.lastSentTime = b.setTime
INNER JOIN tableD as d ON d.Id = a.id
INNER JOIN tableE as e ON e.Id = d.id
INNER JOIN tableF as f ON f.Id = a.id
WHERE a.status = 'FAILED' AND a.Class = 'Secondary' AND a.marks = e.marks
which will return data as
Date Name Discription
1/2/16 Test I am testing
1/2/16 Test I am testing
1/2/16 Test1 I am testing1
1/2/16 Test1 I am testing1
I need result as
Date Name Discription
1/2/16 Test I am testing
1/2/16 Test1 I am testing1
Try DISTINCT
Select DISTINCT a.date, b.Name, d.description
FROM tableA as a
INNER JOIN (SELECT Name, MAX(Time) as lastSentTime FROM tableA
GROUP BY Name) b ON a.Name = omh.Name AND b.lastSentTime = b.setTime
INNER JOIN tableD as d ON d.Id = a.id
INNER JOIN tableE as e ON e.Id = d.id
INNER JOIN tableF as f ON f.Id = a.id
WHERE a.status = 'FAILED' AND a.Class = 'Secondary' AND a.marks = e.marks
Maybe an entirely different approach is what you need. The join to the subquery seems very strange. Also one of your join predicates was in there where clause instead of the join.
with SortedResults as
(
Select a.date
, b.Name
, d.description
, ROW_NUMBER() over(partition by b.Name order by a.date desc) as RowNum
FROM tableA as a
INNER JOIN tableD as d ON d.Id = a.id
INNER JOIN tableE as e ON e.Id = d.id AND a.marks = e.marks
INNER JOIN tableF as f ON f.Id = a.id
WHERE a.status = 'FAILED'
AND a.Class = 'Secondary'
)
select date
, Name
, description
from SortedResults
where RowNum = 1
I have read several posts describing a problem very similar to mine but i haven't been able to solve my issue yet. This is it:
There are tables A, B, C and D. Table D is referenced by the other 3 tables and only table (A) has a 'nullable' foreign key and what I need to find are the rows in D that are NOT being pointed/referenced by any of the other 3 tables. So far I've been able to filter all rows including those I want to find with this code:
SELECT D.Id as Id, A.Id as A_Id, B.Id as B_Id, C.Id as C_Id
FROM D
LEFT OUTER JOIN A --this is the nullable one
ON D.Id = A.D_Id
LEFT OUTER JOIN B
ON D.Id = B.D_Id
LEFT OUTER JOIN C
ON D.Id = C.D_Id
Although I can see the rows I need in the result by looking at them and they display the foreign-key-field as being null if I try to filter by IS NULL then I get no results at all, this is the query I used:
SELECT D.Id as Id, A.Id as A_Id, B.Id as B_Id, C.Id as C_Id
FROM D
LEFT OUTER JOIN A --this is the nullable one
ON D.Id = A.D_Id
LEFT OUTER JOIN B
ON D.Id = B.D_Id
LEFT OUTER JOIN C
ON D.Id = C.D_Id
WHERE A.D_Id IS NULL AND B.D_Id IS NULL AND C.D_Id IS NULL
Please any help will be most appreciated.
Thanks in advance
Edit
I have tried this and it worked although it was a very different approach:
SELECT *
FROM D
WHERE Id not in (Select D_Id from A)
and Id not in (Select D_Id from B)
and Id not in (Select D_Id from C)
The second query is almost correct!
Alternatively Instead of
WHERE A.D_Id IS NULL AND B.D_Id IS NULL AND C.D_Id IS NULL
I would use
WHERE A.Id IS NULL AND B.Id IS NULL AND C.Id IS NULL
SELECT D.Id as Id, A.Id as A_Id, B.Id as B_Id, C.Id as C_Id
FROM D
LEFT OUTER JOIN A --this is the nullable one
ON D.Id = A.D_Id
LEFT OUTER JOIN B
ON D.Id = B.D_Id
LEFT OUTER JOIN C
ON D.Id = C.D_Id
WHERE A.Id IS NULL AND B.Id IS NULL AND C.Id IS NULL
Sql Fiddle Updated
Have you tried using an OR instead of AND for the is null to get what you want? It could be that it is null in the join from one of the tables and not null in the other.
SELECT D.Id as Id, A.Id as A_Id, B.Id as B_Id, C.Id as C_Id
FROM D
LEFT OUTER JOIN A --this is the nullable one
ON D.Id = A.D_Id
LEFT OUTER JOIN B
ON D.Id = B.D_Id
LEFT OUTER JOIN C
ON D.Id = C.D_Id
WHERE A.D_Id IS NULL OR B.D_Id IS NULL OR C.D_Id IS NULL
Edit: Does this give you the results you want?
SELECT *
FROM D
WHERE D.id NOT IN (SELECT D_id FROM A)
AND D.id NOT IN (SELECT D_id FROM B)
AND D.id NOT IN (SELECT D_id FROM C)
Have you tried using NOT EXISTS to exclude the table D entries that are referenced by the other tables?
SELECT
D.Id as Id
FROM
D
WHERE
NOT EXISTS( SELECT 1 FROM A WHERE D.Id = A.D_Id)
AND NOT EXISTS( SELECT 1 FROM B WHERE D.Id = B.D_Id)
AND NOT EXISTS( SELECT 1 FROM C WHERE D.Id = C.D_Id);
I've got four tables: A, B, C, D. D has a FK to C, C has a FK to B, B has a FK to A. Each table has an ID column. In addition to ID and CID, table D has Value and Timestamp (an integer). Given a certain time, I need the row from D before the Timestamp but closest to it for each CID -- Unless there are no rows before the Timestamp, in which case I need the first value after after the Timestamp. I'm using Sqlite.
Leaving out this last requirement, I attempted to get the values before the Timestamp with this query, but the ID returned is wrong:
SELECT *
FROM D d
INNER JOIN C c ON d.CID = c.ID
INNER JOIN B b ON C.BID = b.ID
WHERE b.AID = #AID AND d.Timestamp =
(
SELECT MAX(d2.Timestamp)
FROM D d2
WHERE d2.Timestamp < #StartTime
AND d2.CID = D.CID
)
This query should get the last entry before #StartTime in the first part of the query (before the UNION ALL) then combine it with the first entry after #StartTime. All that remains is to pick the smallest entry for each CID.
SELECT d2.*
FROM (
SELECT D.ID, MAX(D.Timestamp)
FROM D d
INNER JOIN C c ON c.ID = d.CID
INNER JOIN B b on b.ID = c.BID
WHERE b.AID = #AID AND d.Timestamp <= #StartTime
GROUP BY d.CID) AS results
INNER JOIN D d2 ON d2.ID = results.ID
UNION ALL
SELECT d2.*
FROM (
SELECT D.ID, MIN(D.Timestamp)
FROM D d
INNER JOIN C c ON c.ID = d.CID
INNER JOIN B b on b.ID = c.BID
WHERE b.AID = #AID AND d.Timestamp > #StartTime
GROUP BY d.CID) AS results
INNER JOIN D d2 ON d2.ID = results.ID
This might work, but still a little confused over exactly what you want.
SELECT *,
(CASE WHEN d.Timestamp < #StartTime THEN 1 ELSE 0) AS timeCheck
FROM D d
INNER JOIN C c ON d.CID = c.ID
INNER JOIN B b ON C.BID = b.ID
WHERE b.AID = #AID
ORDER BY timeCheck DESC, d.Timestamp DESC
LIMIT 0,1
Updated