SQL - Multiple Table Joins - sql

Hi maybe someone can help me here ...
I have a slight problem with an SQL Statement. ( On MS - SQL Server 2008)
So i have 6 Tables looking like this
ID / Company / Month / ClosedTimeStamp / Different Information
Now i need (preferrable in one Statement :P) the count of Datasets from each table grouped by Company and Month at the time it looks something like this.
And there is another thing not all tables need to have data for that Company and that Month so there can be 0 as Result for count(*)
SELECT COUNT(*) as c, Month, Company
FROM Table1 WHERE ClosedTimeStamp IS NULL
GROUP BY Company, Month
ORDER BY Company
I can do this for all the tables and just pick out the results for each company ... Well if someone has any Idea i really would appreciate it :)
Sorry forgot something ... the result should look like this:
Company / Month / CountTable1 / CountTable2 / CountTable3 / .....
Test 02 1 0 50
If it's not possible in one statement well then i have to make it work another way. :)
Thanks
Lim

UNION ALL table rows and then do the count
SELECT COUNT(*) as c, Month, Company
FROM
(
SELECT Month,Company FROM Table1 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company FROM Table2 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company FROM Table3 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company FROM Table4 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company FROM Table5 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company FROM Table6 WHERE ClosedTimeStamp IS NULL
) AS t
GROUP BY Company, Month
ORDER BY Company
If you want the total for each table,company in one row
SELECT SUM(t1) t1,SUM(t2) t2,SUM(t3) t3,SUM(t4) t4,SUM(t5) t5,SUM(t6) t6, Month, Company
FROM
(
SELECT Month,Company, 1 t1,0 t2, 0 t3, 0 t4, 0 t5, 0 t6 FROM Table1 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company, 0 t1,1 t2, 0 t3, 0 t4, 0 t5, 0 t6 FROM Table2 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company, 0 t1,0 t2, 1 t3, 0 t4, 0 t5, 0 t6 FROM Table3 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company, 0 t1,0 t2, 0 t3, 1 t4, 0 t5, 0 t6 FROM Table4 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company, 0 t1,0 t2, 0 t3, 0 t4, 1 t5, 0 t6 FROM Table5 WHERE ClosedTimeStamp IS NULL
UNION ALL
SELECT Month,Company, 0 t1,0 t2, 0 t3, 0 t4, 0 t5, 1 t6 FROM Table6 WHERE ClosedTimeStamp IS NULL
) AS t
GROUP BY Company, Month
ORDER BY Company

If your DB was normalized the query would be much simpler.
Because, your company and Month are spread across 6 tables, we need to make union of those tables in order to get the distinct dataset of all company+month, as such:
select company, month from table1
union
select company, month from table2
union
select company, month from table3
union
select company, month from table4
union
select company, month from table5
union
select company, month from table6
Note, that we need union, not union all, because we don't want the same company+month pair repeated.
Then, just use this dataset to query the quantities for each table:
select t.company, t.month,
(select count(*) from table1
where company = t.company
and month = t.month
and ClosedTimeStamp is null) as qt1,
(select count(*) from table2
where company = t.company
and month = t.month
and ClosedTimeStamp is null) as qt2,
(select count(*) from table3
where company = t.company
and month = t.month
and ClosedTimeStamp is null) as qt3,
(select count(*) from table4
where company = t.company
and month = t.month
and ClosedTimeStamp is null) as qt4,
(select count(*) from table5
where company = t.company
and month = t.month
and ClosedTimeStamp is null) as qt5,
(select count(*) from table6
where company = t.company
and month = t.month
and ClosedTimeStamp is null) as qt6
from (
select company, month from table1
union
select company, month from table2
union
select company, month from table3
union
select company, month from table4
union
select company, month from table5
union
select company, month from table6
) t
order by t.company

Related

How to combine multiple tables with the basic ID of one table

I want to combine 5 multiple tables, that have the same reference ID as the basic table containing all IDs. The "joined" tables are not containing a value for every reference, but sometimes they have multiple values for one reference. The output should be a sum of each value of the ID.
Example:
Basic Table:
Reference
Basic.Value
1
a
2
b
3
c
4
d
5
e
6
f
7
g
8
h
Table 1:
Reference
T1.Value
1
i
2
j
2
x
3
k
4
l
Table 2
Reference
T2.Value
1
m
5
n
7
o
7
y
8
p
Table 3
Reference
T3.Value
2
q
4
r
6
s
8
t
8
z
Result that should be the output:
Reference
Basic.Value
SUM(T1.Value)
SUM(T2.Value)
SUM(T3.Value)
1
a
i
m
2
b
(j+x)
q
3
c
k
4
d
l
r
5
e
n
6
f
s
7
g
(o+y)
8
h
p
(t+z)
I tried the following code:
SELECT
T0."STATUS",
T0."DocNum" AS "ProjectNumber",
T0."NAME", T0."CARDNAME" AS "Client",
T0."FINISHED" AS "Project Finished",
T1."PoPhAmt" AS "Project Value",
T1."PhBudget" AS "Budget",
(T1."PoPhAmt"-T1."PhBudget") AS "Planned Gross Profit",
T1."TotalAP" AS "Ordered",
SUM(T2."PaidSys") AS "Paid Downpayments(Client)",
COUNT(T2."PaidSys"),
SUM(T3."PaidSys") AS "Paid Invoices(Client)",
COUNT(T3."PaidSys"),
SUM(T4."PaidSys") AS "Creditnotes(Client)",
COUNT(T4."PaidSys")
FROM
(OPMG T0 INNER JOIN PMG8 T1 ON T0."AbsEntry" = T1."AbsEntry")
LEFT JOIN ODPI T2 ON T0."FIPROJECT" = T2."Project"
LEFT JOIN OINV T3 ON T0."FIPROJECT" = T3."Project"
LEFT JOIN ORIN T4 ON T0."FIPROJECT" = T4."Project"
WHERE
T0."FINISHED" < '100' AND T0."STATUS" <> 'N' AND T0."STATUS" <> 'P'
GROUP BY
T0."STATUS",
T0."DocNum",
T0."NAME",
T0."CARDNAME",
T0."FINISHED" ,
T1."PoPhAmt",
T1."PhBudget",
T1."TotalAP"
ORDER BY
T0."DocNum"
Aggregate before joining:
select *
from basic_table t left join
(select t1.project, count(*) as cnt1, sum(value) as value1
from t1
group by t1.project
) t1
on t.FIPROJECT = T1.Project left join
(select t2.project, count(*) as cnt2, sum(value) as value2
from t2
group by t2.project
) t2
on t.FIPROJECT = T2.Project left join
(select t3.project, count(*) as cnt3, sum(value) as value3
from t3
group by t3.project
) t3
on t.FIPROJECT = T3.Project;
SELECT T.ID,T.VALUE,T1.VALUE T_1_VALUE,T2.VALUE T_2_VALUE,T3.VALUE T_3_VALUE
FROM BASIC_TABLE T
LEFT JOIN TABLE_1 T1 ON T.ID=T1.ID
LEFT JOIN TABLE_2 T2 ON T.ID=T2.ID
LEFT JOIN TABLE_3 T3 ON T.ID=T3.ID
WITH BASIC_TABLE(REFERENCE,BASIC_VALUE) AS
(
SELECT 1, 'a' UNION ALL
SELECT 2 , 'b' UNION ALL
SELECT 3 , 'c' UNION ALL
SELECT 4 , 'd' UNION ALL
SELECT 5 , 'e' UNION ALL
SELECT 6 , 'f' UNION ALL
SELECT 7 , 'g' UNION ALL
SELECT 8 , 'h'
),
TABLE_1(REFERENCE,T1_VALUE) AS
(
SELECT 1, 'i' UNION ALL
SELECT 2, 'j' UNION ALL
SELECT 2, 'x' UNION ALL
SELECT 3, 'k' UNION ALL
SELECT 4, 'l'
),
TABLE_2(REFERENCE,T2_VALUE)AS
(
SELECT 1, 'm' UNION ALL
SELECT 5, 'n' UNION ALL
SELECT 7, 'o' UNION ALL
SELECT 7, 'y' UNION ALL
SELECT 8 , 'p'
),
TABLE_3(REFERENCE,T3_VALUE)AS
(
SELECT 2, 'q' UNION ALL
SELECT 4, 'r' UNION ALL
SELECT 6, 's' UNION ALL
SELECT 8, 't' UNION ALL
SELECT 8, 'z'
)
SELECT B.REFERENCE,B.BASIC_VALUE,ISNULL(T1.R,'')AS SUM_T_1_VALUE,ISNULL(T2.R,'')AS SUM_T_2_VALUE,
ISNULL(T3.R,'')AS SUM_T_3_VALUE
FROM BASIC_TABLE AS B
LEFT JOIN
(
SELECT T.REFERENCE,STRING_AGG(T.T1_VALUE,'+')R
FROM TABLE_1 AS T
GROUP BY T.REFERENCE
)T1 ON B.REFERENCE=T1.REFERENCE
LEFT JOIN
(
SELECT T.REFERENCE,STRING_AGG(T.T2_VALUE,'+')R
FROM TABLE_2 AS T
GROUP BY T.REFERENCE
)T2 ON B.REFERENCE=T2.REFERENCE
LEFT JOIN
(
SELECT T.REFERENCE,STRING_AGG(T.T3_VALUE,'+')R
FROM TABLE_3 AS T
GROUP BY T.REFERENCE
)T3 ON B.REFERENCE=T3.REFERENCE
Not sure about SAP HANA, but in MS SQL Server 2017 this code produces more or less the required output
use following query STRING_AGG function with group by Basic_Table.Reference
SELECT
T.Reference,
MAX(T.Basic_Value) AS Basic_Value,
SUM(T1.T1_Value) AS T1_Value,
SUM(T2.T2_Value) AS T2_Value,
SUM(T3.T3_Value) AS T3_Value
FROM BASIC_TABLE T
LEFT JOIN TABLE_1 T1 ON T.Reference=T1.Reference
LEFT JOIN TABLE_2 T2 ON T.Reference=T2.Reference
LEFT JOIN TABLE_3 T3 ON T.Reference=T3.Reference
GROUP BY T.Reference

SQL select all rows on two joined tables

I have two tables with the data of
Id Amt
1 10
2 10
Tbl2
Id Amt
1 10
I want a query that will result to this
Id Amt
1 20
2 10
I tried different joins but no luck.
Thanks!
The safest way to do this is with UNION ALL:
SELECT ID, SUM(AMT) AS AMT FROM (
SELECT ID, AMT FROM TABLE1
UNION ALL
SELECT ID, AMT FROM TABLE2
) GROUP BY ID;
By the way you can do also with a FULL OUTER JOIN being careful to group by ID:
SELECT
NVL(T1.ID, T2.ID) AS ID,
NVL(T1.AMT, 0) + NVL(T2.AMT, 0) AS AMT
FROM
(SELECT ID, SUM(AMT) AS AMT FROM TABLE1 GROUP BY ID) T1
FULL OUTER JOIN
(SELECT ID, SUM(AMT) AS AMT FROM TABLE2 GROUP BY ID) T2
ON (T1.ID = T2.ID);
Use left join:
select tbl1.id, tbl1.amt + coalesce(tbl2.amt, 0)
from tbl1 left join
tbl2
on tbl1.id = tbl2.id

Pairwise intersection counts of multiple columns in SQL

Say I have a SQL db with multiple tables, and each of these tables has a column code. What I want to produce is a table showing the number of codes shared between each pair of code columns. I.e. a pairwise intersection count plot:
table1 table2 table3 table4
table1 10 2 3 5
table2 2 10 4 1
table3 3 4 10 2
table4 5 1 2 10
I can get each value individually using e.g.
WITH abc AS
(
SELECT code FROM table1
INTERSECT
SELECT code FROM table2
)
SELECT COUNT(*) AS table1Xtable2 FROM abc
But is there a query that will generate the entire output as desired as a table?
The following gets all combinations among the tables:
select t1, t2, t3, t4, count(*)
from (select code, max(t1) as t1, max(t2) as t2, max(t3) as t3, max(t4) as t4
from ((select code, 1 as t1, 0 as t2, 0 as t3, 0 as t4
from table1
) union all
(select code, 0 as t1, 1 as t2, 0 as t3, 0 as t4
from table2
) union all
(select code, 0 as t1, 0 as t2, 1 as t3, 0 as t4
from table3
) union all
(select code, 0 as t1, 0 as t2, 0 as t3, 1 as t4
from table4
)
) t
group by code
) t
group by t1, t2, t3, t4;
For your particular problem, you can use:
with t as (
select code, 'table1' as tablename from table1 union all
select code, 'table2' as tablename from table2 union all
select code, 'table3' as tablename from table3 union all
select code, 'table4' as tablename from table4
)
select t1.tablename,
sum(case when t2.tablename = 'table1' then 1 else 0 end) as t1,
sum(case when t2.tablename = 'table2' then 1 else 0 end) as t2,
sum(case when t2.tablename = 'table3' then 1 else 0 end) as t3,
sum(case when t2.tablename = 'table4' then 1 else 0 end) as t4
from t t1 join
t t2
on t1.code = t2.code
group by t1.tablename
Note that the above assumes that code is unique in the tables. If it is duplicated, you can replace union all with union.

UNION ALL Trick ORACLE

This may be so easy, but I can not figure out how I can do.
so my code is like this
FOR example
SELECT id,total,total2
FROM (select id, 0 AS total ,t1.total AS total2
FROM table1 t1
union ALL
select id, t2.total AS total, 0 AS total2
FRoM table2 t2)
it shows
id------total------totals
001 0 20
001 15 0
I would like to show like this
id------total------totals
001 15 20
How can I do that?
Thank you so much
Do an aggregation afterwards:
SELECT id, sum(total) as total, sum(total2) as total2
FROM (select id, 0 AS total ,t1.total AS total2
FROM table1 t1
union ALL
select id, t2.total AS total, 0 AS total2
FRoM table2 t2
) i
GROUP BY id;
Instead of dumping 0's into some columns as filler, you can use a WITH and subquery's to retrieve a sum on all records in the matching Id's from a distinct list of Id's.
;WITH GetIds AS (
SELECT DISTINCT id
FROM table1
UNION
SELECT DISTINCT id
FROM table2
)
SELECT id,
(SELECT SUM(total) FROM table1 t1 WHERE t1.id = ids.id) AS total1,
(SELECT SUM(total) FROM table2 t2 WHERE t2.id = ids.id) AS total2
FROM GetIds ids

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