The question is:
Two tables (t1, t2)
Table t1:
SELLER | NON_SELLER
A B
A C
A D
B A
B C
B D
C A
C B
C D
D A
D B
D C
Table t2:
SELLER | COUPON | BAL
A 9 100
B 9 200
C 9 300
D 9 400
A 9.5 100
B 9.5 20
A 10 80
Using SELECT Statement to get this result:
SELLER| COUPON | SUM(BAL)
A 9 900
B 9 800
C 9 700
D 9 600
A 9.5 20
B 9.5 100
C 9.5 120
D 9.5 120
A 10 0 # !!!
B 10 80
C 10 80
D 10 80
For seller A SUM(BAL) means sum( B.BAL,C.BAL,D.BAL), for B, SUM(BAL)=SUM(A.BAL,C.BAL,D.BAL)...
Please find a way with good performance and don't use temporary table.
My solution:
Running this query will get the result but without the row "A 10 0":
select t1.seller, t2.coupon, sum(bal)
from t1, t2
where t1.non_seller = t2.seller
group by t1.seller, t2.coupon
order by t2.coupon
Please help ~~~~~~
If I understand you correctly, you're looking for data on all sellers and all coupons. So let's start with a cross join that generates a list of coupons and sellers:
select sellers.seller
, coupons.coupon
from (
select distinct seller
from Table2
) as sellers
cross join
(
select distinct coupon
from Table2
) as coupons
For each seller-coupon combination, you're looking for the sum they can buy from other sellers. This can be accomplished by a left join:
select sellers.seller
, coupons.coupon
, case when sum(t2.bal) is null then 0 else sum(t2.bal) end
from (
select distinct seller
from Table2
) as sellers
cross join
(
select distinct coupon
from Table2
) as coupons
left join
Table2 t2
on t2.seller <> sellers.seller
and t2.coupon = coupons.coupon
group by
sellers.seller
, coupons.coupon
The only function of the case statement is to replace a null sum with a 0.
The output matches the one in your answer. Note that this solution doesn't use Table1: the list of other sellers is produced by the t2.seller <> sellers.seller condition in the left join.
I get another way to this:
select t1.seller, t2.coupon, sum(bal)
from t1, t2
where t1.non_seller = t2.seller
group by t1.seller, t2.coupon
union
(select seller,coupon,0 from t2 group by coupon having count(seller) == 1);
And I don't know if it is better or worst than compare with #Andomar :
select sellers.seller
, coupons.coupon
, case when sum(t2.bal) is null then 0 else sum(t2.bal) end
from (
select distinct seller
from Table2
) as sellers
cross join
(
select distinct coupon
from Table2
) as coupons
left join
Table2 t2
on t2.seller <> sellers.seller
and t2.coupon = coupons.coupon
group by
sellers.seller
, coupons.coupon
Related
I have tables like below.
And I successed to extract T2 and I would like to join other tables and aggregate workflow.
First I would like to subtract all customers who has product = A
product customer
A A
B A
C B
B B
A C
B C
. .
. .
. .
Therefore T2is extracted from table like below.
product customer
A A
B A
A C
B C
By below code,I can get T2
WITH T2 AS (
SELECT t.*,
COUNT(CASE WHEN product = 'A' THEN 1 END) OVER (PARTITION BY customer) AS a_cnt
FROM yourTable t
)
SELECT product, customer
FROM T2
WHERE a_cnt > 0;
Further more
I would like to join T3 like
customer age
A 10
B 20
C 30
Therefore My desired result is like below
product customer age
A A 10
B A 10
A C 30
B C 30
Are there any sophisticated way to aggregate workflow?
If you have any opinion,please let me know.
Thanks
You can use EXISTS as follows:
SELECT T1.PRODUCT, T1.CUSTOMER, T3.AGE
FROM T1 T1 JOIN T3 T3 ON T1.CUSTOMER = T3.CUSTOMER
WHERE EXISTS ( SELECT 1
FROM T1 T
WHERE T.CUSTOMER = T1.CUSTOMER
AND T.PRODUCT = 'A')
I am unable to generate a looping kind of behaviour in a SQL query.
I am having two tables:
Table A
Id Brand Prod_Id Alt_Prod_Id
1 A 2 5
2 B 3 9
3 C 5 9
Table B
Id Prod_Id Rate
1 2 5
2 3 9
2 5 7
2 9 9
Rate in Table B needs to be looked up for each brands Prod_ID & Alt_Prod_Id & select the least value between 2 found value
The expected result / output is:
Brand Min_Prod_Val
A 5
B 9
C 7
Can this be done in a query?
Thanks!
You could join tableb twice (once for prod_id, another for alt_prod_id), and then select the smallest rate:
select
a.brand,
least(b1.rate, b2.rate) min_prod_val
from tablea a
inner join tableb b1 on b1.prod_id = a.prod_id
inner join tableb b2 on b2.prod_id = a.alt_prod_id
It is unclear which database you are using. If that's SQL Server: it does not support least(), so you need a case expression:
case when b1.rate < b2.rate then b1.rate else b2.rate end min_prod_val
You can use a single join and GROUP BY the brand:
SELECT a.Brand,
MIN( b.rate ) AS min_prod_val
FROM TableA A
INNER JOIN TableB b
ON ( b.prod_id IN ( a.prod_id, a.alt_prod_id ) )
GROUP BY a.Brand
Or you can use a correlated sub-query:
SELECT a.Brand,
(
SELECT MIN( rate )
FROM TableB b
WHERE b.prod_id IN ( a.prod_id, a.alt_prod_id )
) AS min_prod_val
FROM TableA A
db<>fiddle
I have two tables as seen below.
Table 1:
Day Group
---------
1 A
1 B
1 C
2 B
2 C
2 D
3 C
3 D
3 E
Table 2:
Group
-------
A
B
C
D
E
I would like to create a SQL query that identifies each Group that exists in Table 2 but does not exist in Table 1 partitioned by Day.
The desired result would look like this:
Day Group
---------
1 D
1 E
2 A
2 E
3 A
3 B
Use a cross join to generate all combinations and then weed out what you have:
select d.day, t1.group
from (select distinct day from table1) d cross join
table2 g left join
table1 t1
on t1.day = d.day and t1.group = g.group
where t1.day is null;
SELECT
*
FROM
(
SELECT DISTINCT
Day
FROM
Table1
) AS Days
,
Table2
WHERE
NOT EXISTS (
SELECT
*
FROM
Table1
WHERE
Table1.day=Days.Day AND
Table1.Group=Table2.Group
)
I have the table in sql db like this.
Category Series Value
1 A 100
2 B 200
2 C 300
How do I select to project like this?
Category Series Value
1 A 100
1 B 0
1 C 0
2 A 0
2 B 200
2 C 300
In order to get the result, you will want to generate a list of all categories with each series. You can use a CROSS JOIN to get the result:
select distinct c.category, s.series
from yourtable s
cross join yourtable c
Once you have this, then you can join this back to your table on both the category and series:
select sc.category,
sc.series,
coalesce(t.value, 0) value
from
(
select distinct c.category, s.series
from yourtable s
cross join yourtable c
) sc
left join yourtable t
on sc.series = t.series
and sc.category = t.category;
See SQL Fiddle with Demo
I'm a humble programmer that hates SQL ... :) Please help me with this query.
I have 4 tables, for example:
Table A:
Id Total
1 100
2 200
3 500
Table B
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table C
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table D
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
I need to make a SELECT that shows the Id, the Total and the SUM of the Amount fields of tables B, C and D like this
Id Total AmountB AmountC AmountD
1 100 43 43 43
2 200 55 55 55
3 500 65 65 65
I've tried with a inner join of the three tables by the Id and doing a sum of the amount fields but results are not rigth. Here is the wrong query:
SELECT dbo.A.Id, dbo.A.Total, SUM(dbo.B.Amount) AS Expr1, SUM(dbo.C.Amount) AS Expr2, SUM(dbo.D.Amount) AS Expr3
FROM dbo.A INNER JOIN
dbo.B ON dbo.A.Id = dbo.B.ExtId INNER JOIN
dbo.C ON dbo.A.Id = dbo.C.ExtId INNER JOIN
dbo.D ON dbo.A.Id = dbo.D.ExtId
GROUP BY dbo.A.Id, dbo.A.Total
Thanks in advance, its just that I hate SQL (or that SQL hates me).
EDIT: I had a typo. This query is not giving the right results. Extended the example.
Or you can take advantage of using SubQueries:
select A.ID, A.Total, b.SB as AmountB, c.SC as AmountC, d.SD as AmountD
from A
inner join (select ExtID, sum(Amount) as SB from B group by ExtID) b on A.ID = b.ExtID
inner join (select ExtID, sum(Amount) as SC from C group by ExtID) c on c.ExtID = A.ID
inner join (select ExtID, sum(Amount) as SD from D group by ExtID) d on d.ExtID = A.ID
From your description, this query should give you an error as you are using the non-existent column dbo.A.Amount in your group by. Changing this to dbo.A.Total might be what you need.
If you need all the amounts together, then try this query:
select A.Id, A.Total, sum(B.Amount + C.Amount + D.Amount) AS Total_Amount
from A
inner join B on A.Id = B.ExtId
inner join C on A.Id = C.ExtId
inner join D on A.Id = D.ExtId
group by A.Id, A.Total;
This one also works well
SELECT (SELECT SUM(Amount) FROM TableA) AS AmountA,
(SELECT SUM(Amount) FROM TableB) AS AmountB,
(SELECT SUM(Amount) FROM TableC) AS AmountC,
(SELECT SUM(Amount) FROM TableD) AS AmountD
This might help other users.
SELECT Total=(Select Sum(Amount) from table a)+(Select Sum(Amount) from table b)+(Select Sum(Amount) from table c)
Try this code
SELECT Total=isnull((Select Sum(Isnull(Amount,0)) from table a),0)+isnull((Select Sum(isnull(Amount,0)) from table b),0)+isnull((Select Sum(isnull(Amount,0)) from table c),0)