Selection with join and sum from table in SQL Server - sql

Id Item
--------------
1 ItemA
2 ItemB
3 ItemC
itemid Price
----------------
1 4
1 3
1 9
2 2
2 4
2 3
How I can select with sum from 2 tables? Like as:
ItemA 16
ItemB 9
ItemC 0

You can JOIN the table using a LEFT JOIN and apply an aggregate function SUM() to the price field:
select t1.item, IsNull(sum(t2.price), 0) total
from table1 t1
left join table2 t2
on t1.id = t2.itemid
group by t1.item
See SQL Fiddle with Demo
The LEFT JOIN will allow for the records not in the second table to be included in the final result. I added the IsNull() to the sum() to replace any null values with a zero.
Result:
| ITEM | TOTAL |
-----------------
| ItemA | 16 |
| ItemB | 9 |
| ItemC | 0 |

try this
select item,sum(price) from table1 left outer join table2
on table1.id=table2.itemid
group by item

Please try:
select a.Item, ISNULL(SUM(b.Price), 0) AS TOTALSum
from Table1 a LEFT JOIN Table2 b on a.Id=b.ItemId
Group by a.Item

Related

Get only the code and total number Oracle SQL

I have 2 tables below.I want to join them
Table1
--------------
T1_id | desc
--------------
1 | test 1
2 | test 2
table2 (detail)
---------------
T2_id | Price
----------------
1 | 100000
1 | 0
1 | 0
2 | 300000
2 | 0
2 | 0
2 | 0
i want the results for this
--------------
code | total
--------------
1 | 100000
2 | 300000
this query
select a.T1_id as Code,
b.price as Total
from Table1 a
inner join table2 b on b.T2_id = a.T1_id
group by a.T1_id ,b.price;
Use below query instead to get the total price
select a.T1_id as Code,
SUM(b.price) as Total
from Table1 a
inner join table2 b on b.T2_id = a.T1_id group by a.T1_id;
Sample output:
Referring to the sample
To exclude 0 values:
SELECT T1_ID AS CODE, PRICE AS PRICE FROM TABLE1 JOIN TABLE2 ON T1_ID=T2_ID
WHERE PRICE<>0
sum of same id:
SELECT T1_ID AS CODE, SUM(PRICE) AS PRICE FROM TABLE1 JOIN TABLE2 ON T1_ID=T2_ID
GROUP BY T1_ID
I fail to see where Table 1 comes into play at all. Presumably the t2_id is a FK back to t1_id. You aren't presenting the column DESC at all, so why are you bothering to join on table_1?
So what's wrong with simply
select t2_id CODE,
sum(price) TOTAL
from table2
group by t2_id
order by t2_id
;

How to do an outer join with full result between two tables

I have two tables:
TABLE1
id_attr
-------
1
2
3
TABLE2
id | id_attr | val
----------------------
10 | 1 | A
10 | 2 | B
As a result I want a table that show:
RESULT
id | id_attr | val
----------------------
10 | 1 | A
10 | 2 | B
10 | 3 | NULL
So I want the row with id=10 and id_attr=3 also when id_Attr=3 is missing in TABLE2 (and I know that because I have a NULL value (or something else) in the val column of RESULT.
NB: I could have others ids in table2. For example, after insert this row on table2: {11,1,A}, as RESULT I want:
id | id_attr | val
----------------------
10 | 1 | A
10 | 2 | B
10 | 3 | NULL
11 | 1 | A
11 | 2 | NULL
11 | 3 | NULL
So, for every id, I want always the match with all id_attr.
Your specific example only has one id, so you can use the following:
select t2.id, t2.id_attr, t2.val
from table2 t2
union all
select 10, t1.id_attr, NULL
from table1 t1
where not exists (select 1 from table2 t2 where t2.id_attr = t1.id_attr);
EDIT:
You can get all combinations of attributes and ids in the following way. Use a cross join to create all the rows you want and then a left join to bring in the data you want:
select i.id, t1.id_attr, t2.val
from (select distinct id from table2) i cross join
table1 t1 left join
table2 t2
on t2.id = i.id and t2.id_attr = t1.id_attr;
It sounds like you want to do just an outer join on id_attr instead of id.
select * from table2 t2
left outer join table1 t1 on t2.id_attr = t1.id_attr;

Postgresql COALESCE does not set default value

I have two tables:
tcars
id | name | car_price
----|---------------------|------------
1 |First_car_name | 1000
2 |Second_car_name | 1200
tcar_optionals
id | id_car | spec | opt_included |price
----|----------|------|-------------------------
1 | 2 |Spec1 | true | 500
2 | 2 |Spec2 | true | 100
3 | 2 |Spec3 | false | 500
4 | 2 |Spec4 | true | 0
5 | 1 |Spec5 | false | 500
6 | 1 |Spec6 | true | 0
And the following query:
select t1.id, coalesce(t1.car_price, 0)+ coalesce(sum(t2.price), 0) as total_price
from tcars t1
left join tcar_optionals t2 on t2.id_car = t1.id
where t2.opt_included and t2.price>0 and t1.id=?
group by t1.id, t1.car_price
It returns the id from tcars and the total_price(car_price+price of included optionals that have price>0).
Example:
for t1.id=2 returns:
id | total_price
----|------------
2 | 1800
The problem appears when I have no included optionals with price>0, for example t1.id = 1.
What it returns:
id | total_price
----|------------
What I need is return only t1.car_price as total_price if there are no included optionals with price>0:
id | total_price
----|------------
1 | 1000
Can someone help me with this problem, please?
You should firstly join the tables with all conditions on the second table and aggregate values from this (joined) result, e.g:
select id, coalesce(car_price, 0)+ coalesce(sum(price), 0) total_price
from tcars
left join tcar_optionals on id = id_car and spec_included
-- where id = 1
group by id, car_price
The condition q1.id_car=1 in the where clause effectively turns your outer join into an inner join because for rows not matching the join condition q1.id_car will be null and the comparison =1 will remove those rows again.
You would need to put that into the JOIN condition - but as you already have a condition on the id_car in the derived table ("q1"), you don't need it anyway.
The other possibility would be to filter on the corresponding value from the tcars table: where t1.id = 1
Edit
By moving the conditions on the t2 table to the join condition you do get what you want:
select t1.id, coalesce(t1.car_price, 0) + coalesce(sum(t2.price), 0) as total_price
from tcars t1
left join tcar_optionals t2
on t2.id_car = t1.id
and t2.opt_included and t2.price > 0 --<< conditions for tcar_optionals go here
where t1.id = 1 --<< limit the car you want to see
group by t1.id;
If id is defined as the primary key in tcars, then group by t1.id is enough.
See the example here: http://rextester.com/YOYF30261
select (t1.car_price + coalesce(extra_price, 0)) as start_price
from tcars t1
left join (select id_car,sum(price) as extra_price from tcar_optionals
where opt_included and price > 0 group by 1) q1 on q1.id_car = t1.id
where t1.id=$1

DB2 JOIN, UNION, and pull max value from each group

I am having a difficult time wrapping my head around the path for solving a problem in DB2. I have three tables that look like this...
PARENT
id | label
--------------
1 | One
2 | Two
3 | Three
TABLE1
id | parentid | eventdate
-------------------------
1 | 1 | 2015-11-01
2 | 1 | 2015-12-01
3 | 2 | 2015-10-01
4 | 2 | 2015-09-01
5 | 3 | 2015-08-01
6 | 3 | 2015-07-01
TABLE2
id | parentid | eventdate
-------------------------
1 | 1 | 2015-11-15
2 | 1 | 2015-12-15
3 | 2 | 2015-07-15
4 | 2 | 2015-09-15
5 | 3 | 2015-08-15
6 | 3 | 2015-05-15
Ultimately, I need to find the max date from either table for each parent id. My thought is to UNION two SELECTs, each being JOINed to PARENT, but I am at a complete loss as to how to only pull back a single row for each parent that consists of the max date from either TABLE1 or TABLE2 like this:
One: 2015-12-15
Two: 2015-10-01
Three: 2015-08-15
If anyone could offer some guidance I would be extremely grateful.
You are on the right track. Use a union in a subquery and then join PARENT and GROUP BY label to get the MAX date.
SELECT label, MAX(eventdate) AS maxeventdate FROM (
SELECT parentid, eventdate FROM TABLE1
UNION ALL
SELECT parentid, eventdate FROM TABLE2)
JOIN PARENT ON (id = parentid)
GROUP BY label
SELECT label,
CASE WHEN max(t1.eventdate) > max(t2.eventdate)
THEN max(t1.eventdate)
ELSE max(t2.eventdate)
END as eventdate
FROM PARENT p
JOIN TABLE1 t1
ON p.id = t1.id
JOIN TABLE2 t2
ON p.id = t2.id
GROUP BY p.label
One method is to use union all followed by aggregation. The following does this with a twist, which is to pre-aggregate the results on each table:
select p.label, max(maxed) as max_eventdate
from ((select parentid, max(eventdate) as maxed
from table1
group by parentid
) union all
(select parentid, max(eventdate)
from table2
group by parentid
)
) t12 join
parent p
on t12.parentid = p.id
group by p.label;
There's a function GREATEST() just for this purpose, so you can adjust the solution proposed by #JuanCarlosOropeza:
SELECT label, GREATEST(max(t1.eventdate), max(t2.eventdate)) eventdate
FROM PARENT p
JOIN TABLE1 t1 ON p.id = t1.id
JOIN TABLE2 t2 ON ON p.id = t2.id
GROUP BY p.label
You may want to use LEFT JOIN in case events may be present only in one of the two event tables.

How do I delete values from a column based on a Hierarchy in a given table?

In Table 1, I have customer ID and the list of Items the customer ID has purchased.
Table 1
Customer ID | Item Code
------------------------
1000 | 10
1000 | 20
1000 | 30
1000 | 40
2000 | 10
2000 | 60
2000 | 90
2000 | 100
------------------------
In another table I have a Hierarchy as below
Table 2
This has precedence | Over This
---------------------------------
30 | 10
20 | 40
60 | 90
100 | 60
---------------------------------
I want to add a result column in Table 1 which will, for example , for Customer 1000, eliminate 10 by 30 and 40 by 20 based on table 2.
Case 1: The 10 should be replaced by 30 only for Customer 1000 as there is a 30 present in the column 'Item Code' for Customer 1000 and not for Customer 2000.
Case 2: For Customer 2000, 60 should be replaced by 90 and 90 should be replaced by 100 for both rows.
So Ideally, Final result should be as follows-
Customer ID | Item Code | Final Code
1000 | 10 | 30
1000 | 20 | 20
1000 | 30 | 30
1000 | 40 | 20
2000 | 10 | 10 (This is not replaced!)
2000 | 60 | 100
2000 | 90 | 100
2000 | 100 | 100
Updating the query as OP got updated and shows recursion.
If you want to add a column in Table 1 to show precedence data. Here how you can accomplish it.
ALTER TABLE Table1
ADD Result int
GO
;WITH CTE([This has Precedence], [Over This])
AS
(
--First find the top level members
--These are the items which does't have any precedence
SELECT T2A.[This has Precedence], T2A.[Over This] FROM dbo.Table2 T2A
LEFT JOIN dbo.Table2 T2B
ON T2A.[This has Precedence] = T2B.[Over This]
WHERE T2B.[Over This] IS NULL
UNION ALL
--Now call the lower level members and join with the CTE
SELECT CTE.[This has Precedence], T2.[OVER THIS]
FROM dbo.Table2 T2
INNER JOIN CTE ON T2.[This has Precedence] = CTE.[Over This]
)
--Now use the recursive CTE to find the correct precedence member.
UPDATE T1
SET Result = ISNULL(T1x.[Item Code], T1.[Item Code])
FROM Table1 T1
LEFT JOIN CTE T2
ON T1.[Item Code] = T2.[Over This]
LEFT JOIN Table1 T1x
ON T2.[This has Precedence] = T1x.[Item Code]
AND T1.CID = T1x.CID
GO
Doing an update, assuming those are your real column names:
ALTER TABLE Table1
ADD result int
UPDATE a
SET result = [Item Code] - [This has precedence]
from Table1 a
inner join Table2 b
on a.[Item Code] = b.[Over this]
update2: based on question update
select a.*,ISNULL(d.[This has precedence],a.ItemCode) as [Final Code]
from table1 a left join
(select b.[This has precedence],b.[over this],c.customerID from
(select ISNULL(q.[This has precedence],p.[This has precedence]) as [This has precedence],p.[Over This] from table2 p left join table2 q
on p.[This has precedence]=q.[Over This])
b
inner join table1 c on C.ItemCode=b.[This has precedence]) d
on a.ItemCode=d.[Over This]
and d.customerID=a.CustomerID
update: based on recent comment by asker
I missed to add a clause in the question. the 10 should be replaced by
30 only when there is a 30 present in the column Item Code for
Customer 1000.
for a result like
Customer ID | Result
------------------
1000 | 30
-------------------------
1000 | 20
--------------------------
1000 | 20
--------------------------
2000 | 10
updated query is like:
select DISTINCT a.CustomerID,ISNULL(d.[This has precedence],a.ItemCode) as result
from table1 a left join
(select b.[This has precedence],b.[over this],c.customerID from table2 b
inner join table1 c on C.ItemCode=b.[This has precedence]) d
on a.ItemCode=d.[Over This]
and d.customerID=a.CustomerID
and for a result like
Customer ID | Item Code| Result
------------------
1000 | 10 | 30
-------------------------
1000 | 20 |NULL
--------------------------
1000 | 30 |NULL
--------------------------
1000 | 40 |20
--------------------------
2000 | 10 | NULL
use below query:
select a.*,d.[This has precedence] as result
from table1 a left join
(select b.[This has precedence],b.[over this],c.customerID from table2 b
inner join table1 c on C.ItemCode=b.[This has precedence]) d
on a.ItemCode=d.[Over This]
and d.customerID=a.CustomerID
if you want a result like this
Customer ID | Item Code| Result
------------------
1000 | 10 | 30
-------------------------
1000 | 20 |NULL
--------------------------
1000 | 30 |NULL
--------------------------
1000 | 40 |20
--------------------------
2000 | 10 | 30
then below query will work
select a.*,b.[This has precedence] as result
from table1 a left join table2 b on a.ItemCode=b.[Over This]
If you want to replace rows and get distinct values
Customer ID | Item Code
------------------
1000 | 30
-------------------
1000 | 20
-------------------
2000 | 30
the use below query
update a
set a.ItemCode=b.[This has precedence]
from table1 a left join table2 b on a.ItemCode=b.[Over This]
followed by
select * from table1
if you do not want to update table1 and simply get the above output
then
select DISTINCT a.CustomerID,b.[This has precedence] as result
from table1 a left join table2 b on a.ItemCode=b.[Over This]