SQL Server GROUP BY bigger than - sql-server

I query and have a table with the following sample data
SELECT tb1.ID ,
tb2.TypeID ,
tb2.Name
FROM tb1
INNER JOIN tb2 ON tb1.ID = tb2.ID
WHERE tb1.Status = 1
GROUP BY tb1.ID ,
tb2.TypeID ,
tb2.Name
ID | TypeID | Name|
======================
11 | 1 | A |
19 | 1 | A |
10 | 2 | A |
5 | 1 | B |
4 | 2 | B |
20 | 1 | C |
21 | 1 | C |
I'd like to create a query that shows the ID for each distinct TypeID +Name more than 1, e.g.
ID |
=====
11 |
19 |
20 |
21 |
Can anyone give me a little help? Thanks.

Try like this,
SELECT tb1.ID
FROM tb1
INNER JOIN tb2 ON tb1.ID = tb2.ID
INNER JOIN (
SELECT tb2.TypeID
,tb2.NAME
FROM tb1
INNER JOIN tb2 ON tb1.ID = tb2.ID
WHERE tb1.STATUS = 1
GROUP BY tb2.TypeID
,tb2.NAME
HAVING COUNT(*) > 1
) tb3 ON tb3.typeid = tb2.typeid
AND tb3.NAME = tb2.NAME
WHERE tb1.STATUS = 1

You will need a subquery that will select all records grouped by those two fields and having 2 and more occurrence after that grouping.
SELECT tb1.ID FROM tb1 INNER JOIN tb2 ON tb1.ID = tb2.ID INNER JOIN (
SELECT tb2.TypeID ,tb2.name FROM tb1
INNER JOIN tb2 ON tb1.ID = tb2.ID WHERE tb1.status = 1
GROUP BY tb2.TypeID ,tb2.name HAVING COUNT(*) > 1
) temp ON temp.typeid = tb2.typeid
AND temp.name = tb2.Name
WHERE tb1.status = 1

Related

Combine columns from tables into single table

I have four tables with data I want to put the respective total columns from each in a different column. However, I would like to match on dealerId. So if there is a dealerId in Table 1 and Table 3 that are the same, they should be a single row.
Table 1
dealerId | t1 Total Amount
---------+---------------
1 | 123
2 | 456
Table 2
dealerId | t2 Total Amount
---------+----------------
3 | 111
4 | 222
5 | 333
Table 3
dealerId | t3 Total Amount
---------+----------------
1 | 555
3 | 565
6 | 888
Table 4
dealerId | t4 Total Amount
---------+----------------
1 | 88
2 | 99
3 | 11
Desired Outcome
dealerId | t1Total Amount | t2Total Amount | t3 Total Amount | t4 Total Amount
---------+----------------+----------------+-----------------+-----------------
1 | 123 | null | 555 | 88
2 | 456 | null | null | 99
3 | null | 111 | 565 | 11
4 | null | 222 | null | null
5 | null | 333 | null | null
6 | null | null | 888 | null
I have basically created views (I don't know if this is the correct term for it) and tried to UNION ALL them, but this only gives me a single column with all the totals.
SELECT *
FROM
(
SELECT o.DealerId, Sum(oi.Amount) as T1_Total
FROM ....
) AS T1
UNION ALL
SELECT *
FROM
(
SELECT o.DealerId, Sum(oi.Amount) as T2_Total
FROM ....
) AS T2
UNION ALL
...
-- repeat for T3 and T4
You can also use the pivot operator:
select dealerId, T1, T2, T3, T4
from (
select dealerId, 'T1' as Src, "t1 Total Amount" as Amt from T1
union all
select dealerId, 'T2' , "t2 Total Amount" from T2
union all
select dealerId, 'T3' , "t3 Total Amount" from T3
union all
select dealerId, 'T4' , "t4 Total Amount" from T4
) vert
pivot (sum(Amt) for Src in (T1,T2,T3,T4)) horiz
Results:
dealerId T1 T2 T3 T4
----------- ----------- ----------- ----------- -----------
1 123 NULL 555 88
2 456 NULL NULL 99
3 NULL 111 565 11
4 NULL 222 NULL NULL
5 NULL 333 NULL NULL
6 NULL NULL 888 NULL
Try doing something like this:
with all_dealer_ids AS (
SELECT DISTINCT dealerId
FROM Table1
UNION
SELECT DISTINCT dealerId
FROM Table2
UNION
SELECT DISTINCT dealerId
FROM Table3
UNION
SELECT DISTINCT dealerId
FROM Table4
)
SELECT adi.dealerId, SUM(t1.TotalAmount) As T1TotalAmount, SUM(t2.TotalAmount) As
T2TotalAmount, SUM(t3.TotalAmount) AS T3TotalAmount, SUM(t4.TotalAmount) AS T4TotalAmount
FROM all_dealer_ids adi
LEFT JOIN Table1 t1
ON adi.dealerId = t1.dealerId
LEFT JOIN Table2 t2
ON adi.dealerId = t2.dealerId
LEFT JOIN Table3 t3
ON adi.dealerId = t3.dealerId
LEFT JOIN Table4 t4
ON adi.dealerId = t4.dealerId
GROUP BY adi.dealerId
ORDER BY adi.dealerId ASC
You'll want to use JOIN instead of UNION to accomplish what you're looking for. UNIONs are typically used to stack data, which is why you are seeing all your data in one column. You can try something like this to accomplish what you are looking for.
SELECT COALESCE(t1_totals.dealerID, t2_totals.dealerID, t3_totals.dealerID, t4_totals.dealerID) AS dealerId
, t1_totals.t1_total_amount
, t2_totals.t2_total_amount
, t3_totals.t3_total_amount
, t4_totals.t4_total_amount
FROM (
SELECT dealerID, sum(amount) AS t1_total_amount FROM t1 GROUP BY t1.dealerID
) AS t1_totals
FULL JOIN (
SELECT dealerID, sum(amount) AS t2_total_amount FROM t2 GROUP BY t2.dealerID
) AS t2_totals
ON t2_totals.dealerID = t1_totals.dealerID
FULL JOIN (
SELECT dealerID, sum(amount) AS t3_total_amount FROM t3 GROUP BY t3.dealerID
) AS t3_totals
ON t3_totals.dealerID = t1_totals.dealerID
FULL JOIN (
SELECT dealerID, sum(amount) AS t4_total_amount FROM t4 GROUP BY t4.dealerID
) AS t4_totals
ON t4_totals.dealerID = t1_totals.dealerID
ORDER BY dealerId

Fetching data from two tables in oracle

I have two result sets :
Set 1:
STUDENT| COUNT
------ | ------
mohit | 4
Rohit | 2
Tanvi | 2
Jhanvi | 1
Set 2:
STUDENT| COUNT_STAR
------ | ------
mohit | 2
Rohit | 3
Tanvi | 1
Arjun | 1
Abhay | 3
Abhi | 1
Expected Result Set :
STUDENT| COUNT | COUNT_STAR
------ | ------ | ----------
mohit | 4 | 2
Rohit | 2 | 3
Tanvi | 2 | 1
Arjun | na | 1
Abhay | na | 3
Abhi | na | 1
Jhanvi | 1 | na
Can someone help me with the SQL Query for this ?
you need a union for get the distinct name from both the table
and left join for get the values for count an count_star
select T.STUDENT , table1.count, table2.count_star
from (
select STUDENT
from table1
UNION
select STUDENT
from table2
) T
left join table1 on table1.student = t.student
left join table2 on table1.student = t.student
Use a FULL OUTER JOIN to join two overlapping result sets:
select coalesce(table1.student, table2.student) as student
, nvl( table1.count, 'na') as count
, nvl( table2.star_count, 'na') as star_count
from table1
full outer join table2
on table1.student = table2.student
you can use FULL OUTER JOIN to get the required result-
SELECT DECODE (a.STUDENT, NULL, b.STUDENT, a.STUDENT) STUDENT,
a.COUNT,
b.count_star
FROM table1 a FULL OUTER JOIN table2 b ON a.STUDENT = b.STUDENT;
Hope this helps.
Following SQL is tested with Oracle 12G:
SELECT COALESCE (T1.STUDENT, T2.STUDENT) AS STUDENT,
DECODE (T1.COUNT, NULL, 'na', T1.COUNT) COUNT,
DECODE (T2.COUNT_STAR, NULL, 'na', T2.COUNT_STAR) COUNT_STAR
FROM TABLE1 T1
FULL OUTER JOIN TABLE2 T2 ON T1.STUDENT = T2.STUDENT;

JOIN / MERGE several tables with same key

I have several tables that I have joined like this:
SELECT *
FROM tableA AS A
FULL OUTER JOIN tableB AS B
ON B.KEY = A.KEY
FULL OUTER JOIN tableC AS C
ON C.KEY = A.KEY
FULL OUTER JOIN tableD AS D
ON D.KEY = A.KEY
This works fine, but i sometime get separate rows where the key does not exist in all tables.
Example
WITH tableA([KEY], payloadColumn) AS
(
SELECT 1, 'var_A1'
), tableB([KEY], payloadColumn) AS
(
SELECT 2, 'var_B2'
), tableC([KEY], payloadColumn) AS
(
SELECT 1, 'var_C1'
), tableD([KEY], payloadColumn) AS
(
SELECT 2, 'var_D2'
)
SELECT * FROM tableA as A
FULL OUTER JOIN tableB as B ON B.[KEY] = A.[KEY]
FULL OUTER JOIN tableC as C ON C.[KEY] = A.[KEY]
FULL OUTER JOIN tableD as D ON D.[KEY] = A.[KEY]
Returns
+------+---------------+------+---------------+------+---------------+------+---------------+
| KEY | payloadColumn | KEY | payloadColumn | KEY | payloadColumn | KEY | payloadColumn |
+------+---------------+------+---------------+------+---------------+------+---------------+
| 1 | var_A1 | NULL | NULL | 1 | var_C1 | NULL | NULL |
| NULL | NULL | 2 | var_B2 | NULL | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | var_D2 |
+------+---------------+------+---------------+------+---------------+------+---------------+
But i need them all to be in the same row in the result (not two rows for 2). How can I do this?
That's my proposed solution based on the draft in a previous version of OP, and their last edit:
CREATE VIEW ABCD
AS
SELECT [KEY] FROM tableA
UNION
SELECT [KEY] FROM tableB
UNION
SELECT [KEY] FROM tableC
UNION
SELECT [KEY] FROM tableD
Creating a view may not be an option; in this case rewrite as a CTE.
At least in this way, the execution plan will continue to use indexes (assuming [KEY] is a PK or indexed).
SELECT
K.[KEY] as sameKey,
A.payloadColumn,
B.payloadColumn,
C.payloadColumn,
D.payloadColumn
FROM ABCD K
LEFT JOIN tableA A ON A.[KEY]=K.[KEY]
LEFT JOIN tableB B ON B.[KEY]=K.[KEY]
LEFT JOIN tableC C ON C.[KEY]=K.[KEY]
LEFT JOIN tableD D ON D.[KEY]=K.[KEY]
If this got your idea wrong, please elaborate.
You can use COALESCE
WITH tableA([KEY], payloadColumn)
AS (SELECT 1,
'var_A1'),
tableB([KEY], payloadColumn)
AS (SELECT 2,
'var_B2'),
tableC([KEY], payloadColumn)
AS (SELECT 1,
'var_C1'),
tableD([KEY], payloadColumn)
AS (SELECT 2,
'var_D2')
SELECT COALESCE(A.[KEY], B.[KEY], C.[KEY], D.[KEY]) AS [KEY],
A.payloadColumn,
B.payloadColumn,
C.payloadColumn,
D.payloadColumn
FROM tableA AS A
FULL OUTER JOIN tableB AS B
ON B.[KEY] = A.[KEY]
FULL OUTER JOIN tableC AS C
ON C.[KEY] = COALESCE(A.[KEY], B.[KEY])
FULL OUTER JOIN tableD AS D
ON D.[KEY] = COALESCE(A.[KEY], B.[KEY], C.[KEY]);
Returns
+-----+---------------+---------------+---------------+---------------+
| KEY | payloadColumn | payloadColumn | payloadColumn | payloadColumn |
+-----+---------------+---------------+---------------+---------------+
| 1 | var_A1 | NULL | var_C1 | NULL |
| 2 | NULL | var_B2 | NULL | var_D2 |
+-----+---------------+---------------+---------------+---------------+
If all the tables have a covering index on [KEY] INCLUDE (payloadColumn) the execution plan for this can just chain together merge joins.

Join and sum multiple columns

Table TB1:
| PaymentID | CashAmount |
--------------------------
| P1 | 3,000|
| P2 | 5,000|
| P3 | 8,000|
Table TB2:
|ChequeID| PaymentID |ChequeAmount|
-----------------------------------
| C1 | P2 | 10,000|
| C2 | P1 | 15,000|
| C3 | P1 | 2,000|
Table TB3:
|TransferID| PaymentID |TransferAmount|
---------------------------------------
| T1 | P2 | 20,000|
| T2 | P2 | 20,000|
| T3 | P1 | 3,000|
Expected Result
| PaymentID | CashAmount |ChequeAmount|TransferAmount|
------------------------------------------------------
| P1 | 3,000| 17,000| 3,000|
| P2 | 5,000| 10,000| 40,000|
| P3 | 8,000| NULL| NULL|
How to write a query JOIN and SUM all these tables together?
I tried writing simple join query but the result was wrong.
Example of incorrect query:
SELECT
TB1.PaymentID, TB1.CashAmount,
SUM(TB2.ChequeAmount) AS ChequeAmount,
SUM(TB3.TransferAmount) AS TransferAmount
FROM
TB1
LEFT JOIN
TB2 ON TB1.PaymentID = TB2.PaymentID
LEFT JOIN
TB3 ON TB1.PaymentID = TB3.PaymentID
GROUP BY
TB1.PaymentID, TB1.CashAmount
Incorrect result:
| PaymentID | CashAmount | ChequeAmount | TransferAmount |
----------------------------------------------------------
| P1 | 3,000 | 17,000 | 6,000 |
| P2 | 5,000 | 20,000 | 40,000 |
| P3 | 8,000 | NULL | NULL |
The problem you have is you're joining the tables that have multiple rows with the same id and it multiplies the numbers. You'll need to do the sum first and then join the data. Assuming the data can be missing from any of the tables, you'll also need to use full outer join. If TB1 has the row always, then left outer join is enough.
This is how you can do it:
SELECT
coalesce(TB1.PaymentID,TB2.PaymentID,TB3.PaymentID),
TB1.CashAmount, TB2.ChequeAmount, TB3.TransferAmount
from (
select PaymentID, SUM(CashAmount) AS CashAmount
from TB1 group by PaymentID
) TB1
full outer join (
select PaymentID, SUM(ChequeAmount) AS ChequeAmount
from TB2 group by PaymentID
) TB2 on TB1.PaymentID = TB2.PaymentID
full outer join (
select PaymentID, SUM(TransferAmount) AS TransferAmount
from TB3 group by PaymentID
) TB3 on isnull(TB1.PaymentID, TB2.PaymentID) = TB3.PaymentID
Example in SQL Fiddle
I would eliminate the duplicates in the minor tables first, then (left) join and sum with the major table, like this
SELECT
TB1.PaymentID,
TB1.CashAmount,
Sum(TB2.ChequeAmount) as ChequeAmount,
Sum(TB3.TransferAmount) as TranAmt
from TB1
left join (
select PaymentID, SUM(ChequeAmount) AS ChequeAmount
from TB2 group by PaymentID
) TB2 on TB1.PaymentID = TB2.PaymentID
left join (
select PaymentID, SUM(TB3.TransferAmount) AS TransferAmount
from TB3 group by PaymentID
) TB3 on isnull(TB1.PaymentID, TB2.PaymentID) = TB3.PaymentID
group by
tb1.PaymentId, tb1.CashAmount
WITH t2
AS (
SELECT [PaymentId], SUM([ChequeAmount]) AS ChequeAmount
FROM TB2
GROUP BY [PaymentId]
),
t3
AS (
SELECT [PaymentId], SUM([TransferAmount]) AS TransferAmount
FROM TB3
GROUP BY [PaymentId]
)
SELECT t.PaymentId, SUM(CashAmount) AS CashAmount,
SUM(t2.[ChequeAmount]) AS [ChequeAmount],
SUM(t3.[TransferAmount]) AS [TransferAmount]
FROM TB1 AS [t]
LEFT JOIN [t2] ON [t2].[PaymentId] = [t].[PaymentId]
LEFT JOIN [t3] ON [t3].[PaymentId] = [t].[PaymentId]
GROUP BY [t].[PaymentId];

Select data from 3 tables in sql

I need to select data from 3 tables.
Please check the sample tables and expected output.
And also the fiddle link below.
Table1
Name | Image_Name
--------+--------------
A1 | A1.jpg
B1 | B1.jpg
C1 | C1.jpg
D1 | D1.jpg
E1 | E1.jpg
F1 | F1.jpg
G1 | G1.jpg
H1 | H1.jpg
I1 | I1.jpg
J1 | J1.jpg
Table2
Name | qty1
--------+----------
A1 | 1
B1 | 2
D1 | 3
F1 | 4
Table3
Name | qty2
--------+----------
A1 | 5
B1 | 6
J1 | 7
Expected Output
Name | Image_Name | qty1 | qty2
--------+---------------+---------+--------
A1 | A1.jpg | 1 | 5
B1 | B1.jpg | 2 | 6
D1 | D1.jpg | 3 | 0
F1 | F1.jpg | 4 | 0
J1 | J1.jpg | 0 | 7
Find the Fiddle here
The query:
SELECT a.Name,a.Image_Name,
b.qty1,c.qty2
FROM Table1 a
JOIN Table2 b
ON a.Name=b.Name
FULL JOIN Table3 c
ON b.Name=c.Name;
Try Following query:
SELECT table1.name, table1.Image_name, Table2.Qty1, Table3.Qty2
FROM table1
LEFT JOIN table2 on Table2.Name = table1.name
LEFT JOIN table3 on Table3.Name = table1.name
WHERE table2.name IS NOT NULL
OR table3.name IS NOT NULL
Two left joins would appear to do the trick:
select name
, image_name
, coalesce(t2.qty1, 0)
, coalesce(t3.qty2, 0)
from t1
left join
t2
on t1.Name = t2.Name
left join
t3
on t1.Name = t3.Name
Unlike the full join from your SQL Fiddle, a left join returns only rows from the right table if they are matched in the left table.
It looks like you just need to select the qty in the output list. This will return NULL for qty2 and qty3 if the value is not in table2 or table3 respectively.
select name, image_name,
(select qty1 from table2 where name = table1.name) as qty1,
(select qty2 from table3 where name = table1.name) as qty2
from table1
You can try the below;
Select tbl1.Name, tbl1.Image_Name, tbl2.qty1, tbl3.qty2
from Table1 tbl1
inner join Table2 tbl2
on tbl1.Name = tbl2.Name
inner join Table3 tbl3
on tbl1.Name = tbl3.Name

Resources