select clause with having max condition - sql

For my database table:
//table1
name
---------
john
mary
ali
in my table2
//table2
title
---------
test1
test2
test3
in my table3
//table3
name title
-----------------
john test1
john test2
john test3
mary test2
So my question is to find the title that been joined by name for most many times.
So my query is:
SELECT t2.title from table2 t2 inner join table3 t3 on
t2.title = t3.title inner join table1 t1 on
t1.name = t3.name having max(....)
as i check for some websites. all they use for the having clause is for the numbers only, i can't find any example that suit for my question that need to count(*)
expected output:
//result
title
---------
test2

Order by the count to get a list starting from the most common ttile
SELECT t2.title
from table2 t2
inner join table3 t3 on t2.title = t3.title
inner join table1 t1 on t1.name = t3.name
group by t2.title
order by count(*) desc
To get only the top result use
SELECT * FROM
(
SELECT t2.title
from table2 t2
inner join table3 t3 on t2.title = t3.title
inner join table1 t1 on t1.name = t3.name
group by t2.title
order by count(*) desc
) X
WHERE ROWNUM = 1;

SELECT max(name) KEEP(DENSE_RANK FIRST ORDER BY COUNT(NAME) DESC)
FROM table3
GROUP BY name

Related

how to union 3 table and group same id amount?

how to solve 3 table and group same id?
t1
----------
Id a
1 100
1 600
2 800
t2
----------
Id b
1 600
2 700
3 400
t3
----------
Id c
2 400
3 800
4 100
i want result like this:
Id a b c
------------------------------
1 700 600
2 800 700 400
3 400 800
4 100
Same id group by
do the fact you have id in several table youn should get, eg: using union ,all the id you need for join
select t.id, t1.a, t2.b, t3.c
from (
select id
from t1
union
select id
from t2
union
select id
from t3 ) AS t
left join t1 on t.id = t1.id
left join t2 on t.Id = t2.Id
left join t3 on t.Id = t3.Id
and if you need sum for a,b,c
select t.id, sum(t1.a), sum(t2.b), sum(t3.c)
from (
select id
from t1
union
select id
from t2
union
select id
from t3 ) AS t
left join t1 on t.id = t1.id
left join t2 on t.Id = t2.Id
left join t3 on t.Id = t3.Id
group by t.id
To ensure that you are taking all possible values use full outer join. Though this will not work in mySQL. If that is the case then look at this answer
select coalesce(t1.id,t2.id,t3.id) as id, sum(t1.a) as a, sum(t2.b) as b,sum(t3.c) as c
from t1
outer join t2
on t1.id = t2.id
outer join t3
on t1.id = t3.id
or t2.id = t3.id
group by id
Might be misunderstanding you, but looks like you just need to join the table more than doing a Union Operation on them. Below statement will only return records where all three tables have at least one record with the same id.
SQL would be:
SELECT TBL1.ID,
TBL1.A,
TBL2.B,
TBL3.C
FROM A TBL1 (NOLOCK)
INNER JOIN B TBL2 (NOLOCK) ON TBL1.ID = TBL2.ID
INNER JOIN C TBL3 (NOLOCK) ON TBL1.ID = TBL3.ID
Two questions:
1. Which SQL engine to you use?
2. and do you need to return values where one table does not have the id?

Distinct SQL Join two tables

I am trying to join two tables such that I am getting only a first match from the Right table instead of every match in Table2.
So if the query is:
SELECT T1.Name, T2.Dates
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.ID = T2 = ID
WHERE T1.Name = 'John'
I would like to see
John | 14/11/14
Joe | 10/10/2014
Jane | 25/10/2014
Instead of
John | 14/11/2014
John | 12/10/2014
Joe | 10/10/2014
Jane | 25/10/2014
Jane | 26/10/2014
Which join should I use?
You need to decide which row, you should select. Min or max as commented.
SELECT T1.Name,
( SELECT MIN( T2.Dates) FROM Table2 T2 WHERE T1.ID = T2 = ID) AS Dates
FROM Table1 T1
WHERE T1.Name = 'John'
The ANSI standard function row_number() can be a big help here. It is supported by most databases, so you can do:
SELECT T1.Name, T2.Dates
FROM Table1 T1 LEFT JOIN
(SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t2.ID ORDER BY t2.DATE DESC) as seqnum
FROM Table2 t2
) T2
ON T1.ID = T2.ID AND seqnum = 1
WHERE T1.Name = 'John';
In your question, you have only one column from the second table, so you can also do this with aggregation:
SELECT t1.ID, t1.Name, MAX(t2.Date)
FROM Table1 T1 LEFT JOIN
Table2 T2
ON t1.ID = t2.ID
WHERE T1.Name = 'John'
GROUP BY t1.ID, t1.Name;
Query
SELECT a.name,
MAX(b.Dates)
FROM tbl1 a
JOIN tbl2 b
ON a.id=b.id
WHERE a.name='John'
GROUP BY a.name;
Demo

sql - how to select multiple columns with only one distinct column from joining multiple tables

I am using SQL Server. I want to select multiple columns with only one distinct column.
For example,
TABLE 1:
ID NAME ...(other columns)
1 A
2 B
3 C
Table 2 (ID and number together is the unique key):
ID Number Year...(other columns)
1 111 2011
2 12345678 2011
2 22222222 2012
3 333 2013
Table 3:
Name Company ...(other columns)
A Amazon
B Google
C Amazon
Each table above has many columns (more than 2). How can get the result so that there are only 5 columns as result without other "useless" columns and the ID column is the distinct column.
More specifically, for example,
The normal sql statement I had is the following:
select distinct ID, NAME, NUMBER, COMPANY, Year
from table1
left join table2 on table1.ID = table2.ID
left join table3 on table1.name = table3.name
group by ID, NAME, NUMBER, COMPANY, year
order by ID desc, Year desc
This will output the following:
ID NAME NUMBER COMPANY YEAR
1 A 111 Amazon 2011
2 B 12345678 google 2011
2 B 22222222 google 2012
3 c 333 Amazon 2013
What I want to have is actually the following:
ID NAME NUMBER COMPANY YEAR
1 A 111 Amazon 2011
2 B 22222222 google 2012
3 c 333 Amazon 2013
I want to have the results without duplicated ID. If there are duplicate ID's, I want to show only the latest one. In above example, ID 2 has 2 rows in table2. I want to show the one with the latest date which is 2012.
How can I achieve this. Thanks in advance.
You can use not exists to only select the latest rows per id (where another row with the same id and a greater year does not exist).
select * from table1 t1
where not exists (
select 1 from table1 t2
where t2.id = t1.id
and t2.year > t1.year
)
using analytic functions (this should be faster than the query above)
select * from
(select *,
row_number() over(partition by id order by year desc) rn
from table1) t1 where rn = 1
edit: applied to your tables
select t2.id, t3.name, t2.number, t3.company, t2.year from
(
select * from
(select *,
row_number() over(partition by id order by year desc) rn
from table2
) t1 where rn = 1
) t2 join table1 t1 on t2.id = t1.id
join table3 t3 on t3.name = t1.name
WITH CTE AS
(
SELECT t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.Year,
Row_number() OVER(partition BY t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY ORDER BY t2.Year DESC) AS rn
FROM table1 t1
LEFT JOIN table2 t2 ON t1.ID = t2.ID
LEFT JOIN table3 t3 ON t1.name = t3.name
)
SELECT ID, NAME, NUMBER, COMPANY, Year
FROM CTE
WHERE rownum = 1
ORDER BY ID desc, Year desc
I used a subquery, note subqueries are inefficient.
select distinct t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.Year
from table1 t1
left join table2 t2 on t1.ID = t2.ID
inner join table3 t3 on t1.name = t3.name --inner join to select the latest record only
and t2.Year = (Select MAX(year) from table2 t22
where t22.ID = t2.Id group by ID)
group by t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.year
order by t1.ID, t2.Year desc
EDIT: using a more efficient CTE
WITH CTE as
(
Select Id, MAX(year) as [yr] from table2 t2 group by ID
)
select distinct t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.Year
from table1 t1
left join table2 t2 on t1.ID = t2.ID
left join table3 t3 on t1.name = t3.name
inner join CTE on cte.yr = t2.Year
and t2.Id = CTE.Id
group by t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.year
order by t1.ID, t2.Year desc

Join sql results

Please, help me with join results of commands (MS SQL):
SELECT name,value FROM table1 WHERE idfoo1 IN(SELECT _id FROM table3 where id = 1);
SELECT value FROM table2 WHERE idfoo2 IN(SELECT _id_2 FROM table3 where id = 1) AND name='fooname';
And I get:
name value
John 2
Bill 32
Alex 11
value
434
234
144
But I need join results.
name value value
John 2 434
Bill 32 234
Alex 11 144
So, id == id, _id != _id_2,
Use this query:
SELECT t1.name,
t1.value,
t2.value
FROM table1 t1
INNER JOIN table3 t3 ON t1.idfoo1 = t3._id
INNER JOIN table2 t2 ON t2.idfoo2 = t3._id_2
WHERE t3.id=1 AND t2.name = 'fooname'
Select a.name,a.value,c.value FROM table1 as a inner join table3 as b
on a.idfoo1=b.id and b.id=1 inner join table3 as c
on c.idfoo2=b._id_2 and b.id=1 and c.name='fooname'
i guess this is what you need-
SELECT t1.name, t1.value, t2.value
FROM table1 t1, table2 t2, table3 t3
WHERE
t1.idfoo1 = t3._id
AND t2.idfoo2 = t3._id_2
AND t3.id = 1
AND t2.name='fooname';

Best practices for multi table join query

Tables structure are below :
Table1 (ID int, value1 int,...)
ID Value1
---- --------
1 10
2 20
5 12
Table2 (ID int, value2 int,...)
ID Value2
---- --------
1 13
3 24
4 11
Table3 (ID int, value3 int,...)
ID Value3
---- --------
4 150
5 100
My expected output is below.
ID Value1 Value2 Value3
---- -------- -------- --------
1 10 13 NULL
2 20 NULL NULL
3 NULL 24 NULL
4 NULL 11 150
5 12 NULL 100
It should be noted that above tables is huge and I want to have best performance.
My query suggestion is below :
Select ID,
SUM(Value1) AS Value1,
SUM(Value2) AS Value2,
SUM(Value3) AS Value3
From (
Select ID, Value1 , NULL as value2, NULL as value 3
From Table1
Union ALL
Select ID, NULL , value2, NULL
From Table2
Union ALL
Select ID, NULL, NULL, value 3
From Table3
)Z
Group By Z.ID
Assuming you only have one value per id, this should do the trick:
SELECT aux.ID, t1.Value1, t2.Value2, t3.Value3
FROM
(SELECT ID FROM Table1
UNION
select ID FROM Table2
UNION
SELECT ID FROM Table3) aux
LEFT OUTER JOIN Table1 t1 ON aux.ID = t1.ID
LEFT OUTER JOIN Table2 t2 ON aux.ID = t2.ID
LEFT OUTER JOIN Table3 t3 ON aux.ID = t3.ID
If you've more than one value:
SELECT aux.ID, SUM(t1.Value1) as 'Value1', SUM(t2.Value2) as 'Value2', SUM(t3.Value3) as 'Value3'
FROM
(SELECT ID FROM Table1
UNION
select ID FROM Table2
UNION
SELECT ID FROM Table3) aux
LEFT OUTER JOIN Table1 t1 ON aux.ID = t1.ID
LEFT OUTER JOIN Table2 t2 ON aux.ID = t2.ID
LEFT OUTER JOIN Table3 t3 ON aux.ID = t3.ID
GROUP BY aux.ID
I intially wrote the same answer as aF. did above. So, removed it, and used a different approach.
Here,
1st query get all from table1
2nd query gets all from table2 skipping
those already present in table1 3rd query gets all remaining skipping those in above two query.
SELECT T1.ID, T1.VALUE1, T2.VALUE2, T3.VALUE3 --all T1
FROM TABLE1 T1
LEFT JOIN TABLE2 ON T1.ID=T2.ID
LEFT JOIN TABLE3 ON T1.ID=T3.ID
UNION
SELECT T2.ID, T1.VALUE1, T2.VALUE2, T3.VALUE3 --all T2 where T1 is NULL
FROM TABLE1 T2
LEFT JOIN TABLE1 ON T2.ID=T1.ID
LEFT JOIN TABLE3 ON T2.ID=T3.ID
WHERE T1.ID IS NULL
UNION
SELECT T3.ID, T1.VALUE1, T2.VALUE2, T3.VALUE3 --all T3 where T1 is NULL AND T2 IS NUL
FROM TABLE1 T3
LEFT JOIN TABLE1 ON T3.ID=T1.ID
LEFT JOIN TABLE2 ON T3.ID=T2.ID
WHERE T1.ID IS NULL
AND T2.ID IS NULL