Joining multiple tables with filter - sql

I got multiple tables and i'm only using 3 for testing. I don't know if this is the right approach.
AccntTbl
id accnt amount date
---------------------------------
1 xxx 10.00 1/1/2016
2 yyy 20.00 1/1/2016
3 zzz 30.00 1/1/2016
SupplyTbl
id accnt supply date
-------------------------------
1 xxx 5.00 1/10/2016
1 xxx 5.00 2/14/2016
IssuedTbl
id accnt issued date
---------------------------------
1 xxx 3.00 1/9/2016
1 xxx 2.00 2/1/2016
and the result will be like this if filter to JANUARY
id accnt amount issued balance
--------------------------------------------
1 xxx 15.00 3.00 12.00
2 yyy 20.00 0.00 20.00
3 zzz 30.00 0.00 30.00
and if FEBRUARY
id accnt amount issued balance
---------------------------------------------
1 xxx 20.00 5.00 15.00
2 yyy 20.00 0.00 0.00
3 zzz 30.00 0.00 0.00
and here's my query that i've come up with
SELECT accnttbl.id,
accnttbl.accnt,
Sum(accnttbl.amount)
+ Sum(SupplyTbl.supply) AS amount,
issuedtbl.issued
FROM accnttbl
LEFT JOIN (SELECT id,
Sum(supply) AS supply,
date
FROM supplytbl
GROUP BY id,
date) AS SupplyTbl
ON accnttbl.id = SupplyTbl.id
AND Month(SupplyTbl.date) BETWEEN 1 AND 2
LEFT JOIN (SELECT id. Sum(issued) AS issued,
date
FROM issuedtbl
GROUP BY id,
date)
ON accnttbl.id = issuedtbl.id
AND Month(issuedtbl.date) BETWEEN 1 AND 2
WHERE Year(accnttbl.date) = 2016
GROUP BY accnttbl.id,
accnttbl.accnt
and i kinda mess up..glad for any help :)
the result be like this..in JANUARY
id accnt amount issued
1 xxx 30.00 10.00
2 yyy 20.00 0.00
and in FEBRUARY
1 xxx 60.00 20.00
2 yyy 20.00 0.00
with the value that i been given..it just..it doubled the amount on its own..the result are wrong..why is that ?

Try as below :
SELECT AccntTbl.id, AccntTbl.accnt
, SUM(AccntTbl.amount) + SUM(SupplyTbl.supply) as amount
, SUM(IssuedTbl.issued) as issued
, (SUM(amount) - SUM(issued)) as balance
FROM AccntTbl LEFT JOIN
(SELECT id, COALESCE(SUM(supply), 0) AS supply, date FROM SupplyTbl
GROUP By id, date) AS SupplyTbl
ON AccntTbl.id = SupplyTbl.id AND (MONTH(SupplyTbl.date) BETWEEN
1 AND 2)
LEFT JOIN
(SELECT id, COALESCE(SUM(issued),0) as issued, date from IssuedTbl
GROUP By id, date )
ON AccntTbl.id = IssuedTbl.id AND (MONTH(IssuedTbl.date) BETWEEN
1 AND 2)
WHERE (YEAR(AccntTbl.date) = 2016)
GROUP By AccntTbl.id, AccntTbl.accnt
;
In sql anything added with NULL is NULL . So in your subquery if you are not using COALESCE, you are adding your value with NULL, hence you are not getting your desired result.

Related

Calculate column amount and get total with order number?

How to calculate each order number amount and total amount with SQL status
Order_no Status Amount
9008258656 P 50.00
9008258656 P 0.00
9008510713 P 50.00
9008510713 P 0.00
Well, it looks like you want a simple aggregated query :
SELECT order_no, count(*) number_of_orders, sum(amount) total_amount
FROM orders
GROUP BY order_no
If you need to filter on a specific status :
SELECT order_no, count(*) number_of_orders, sum(amount) total_amount
FROM orders
WHERE status = 'P'
GROUP BY order_no
If you are looking to keep your individual line numbers (i.e. 4 total records) and not have aggregates (i.e. 2 total records), you can use the sum window function.
SELECT ord.Order_no
, ord.Status
, ord.Amount
, TotalSum = SUM(ord.Amount)OVER(PARTITION BY ord.Order_no, ord.Status)
FROM Orders ord
This would produce the following result:
Order_no Status Amount TotalAmount
9008258656 P 50.00 50.00
9008258656 P 0.00 50.00
9008510713 P 50.00 50.00
9008510713 P 0.00 50.00
Based off the example you provided, there probably is not much value in doing the sum over in this scenario. #GMB's response should suffice. However, there are a lot of cool things you can do with the sum window function such as running totals. For example, if you had an order date column, you can include after the PARTITION BY ord.Order_no, ord.Status ORDER BY ord.Order_date and this would give you a running sum of the amount that increments by each order. I.E:
Order_no Order_date Status Amount RunningTotal
9008258656 1/2/2019 P 50.00 50.00
9008258656 1/3/2019 P 0.00 50.00
9008258656 1/4/2019 P 50.00 100.00
9008258656 1/5/2019 P 0.00 100.00

select total sales per day

i have query like this and i wanted to have sum of sales per day
SELECT DATEPART(day,deduction_timestamp) as [day],
[fare_deduction]
FROM [dbfastsprocess].[dbo].[vClosingTransitLog]
WHERE bus_id in ('JEAST', 'MKV004', 'NWTN01')
and YEAR(deduction_timestamp) = ISNULL(2016, YEAR(deduction_timestamp))
and MONTH(deduction_timestamp) = ISNULL(10, MONTH(deduction_timestamp))
GROUP BY DATEPART(day,deduction_timestamp), fare_deduction
with result :
day fare_deduction
--------------------------------
1 10.00
3 15.00
3 2.00
4 10.00
10 20.00
31 12.00
and i wanted the result to be like this..
day fare_deduction
--------------------------------
1 10.00
3 17.00
4 10.00
10 20.00
31 12.00
and take note that not all day have values and it only display the affected
day only. Can help me on these? Thanks!
SELECT DATEPART(day,deduction_timestamp) as [day],
sum(fare_deduction) as fare_deduction
FROM [dbfastsprocess].[dbo].[vClosingTransitLog]
WHERE bus_id in ('JEAST', 'MKV004', 'NWTN01')
and YEAR(deduction_timestamp) = ISNULL(2016, YEAR(deduction_timestamp))
and MONTH(deduction_timestamp) = ISNULL(10, MONTH(deduction_timestamp))
GROUP BY DATEPART(day,deduction_timestamp)
Simply use sum, it will get your required result
SELECT DATEPART(day,deduction_timestamp) as [day],
SUM([fare_deduction]) [fare_deduction]
FROM [dbfastsprocess].[dbo].[vClosingTransitLog]
WHERE bus_id in ('JEAST', 'MKV004', 'NWTN01')
and YEAR(deduction_timestamp) = ISNULL(2016, YEAR(deduction_timestamp))
and MONTH(deduction_timestamp) = ISNULL(10, MONTH(deduction_timestamp))
GROUP BY DATEPART(day,deduction_timestamp)

joining multiple tables with filter by date

i got 3 tables..how do i join these tables with filter by date on each table
MainTbl
id accnt amount date
---------------------------------
1 xxx 10.00 1/1/2016
2 yyy 20.00 1/1/2016
3 zzz 30.00 1/1/2016
SupplyTbl - this table would add the value of supply to the amount in the MainTbl
id accnt supply date
-------------------------------
1 xxx 5.00 1/10/2016
1 xxx 5.00 2/14/2016
2 yyy 10.00 1/20/2016
IssuedTbl
id accnt issued dateIssue
------------------------------------------
1 xxx 5.00 1/10/2016
1 xxx 5.00 2/14/2016
2 yyy 10.00 2/15/2016
now i want to join these tables..with date range..if i filter the date to JANUARY it would result something like this
id accnt amount issued
-----------------------------
1 xxx 15.00 5.00
2 yyy 30.00 0.00
3 zzz 30.00 0.00
and when i filter to FEBRUARY..it will combine both from JANUARY to FEBRUARY
id accnt amount issued
-----------------------------
1 xxx 20.00 10.00
2 yyy 40.00 10.00
3 zzz 30.00 0.00
i'm struggling with this since the other night..glad with any help..tnx in advance :)
Try something like this
SELECT M.id,
M.accnt,
amount = M.amount + Isnull(s.supply, 0),
issued = Isnull(I.issued, 0)
FROM maintbl M
LEFT OUTER JOIN (SELECT id,
Sum(supply) AS supply
FROM supplytbl
WHERE Month(dates) = 1 -- Month filter for Jan - feb Month(dates) in (1,2)
GROUP BY id) S
ON s.id = M.id
LEFT OUTER JOIN (SELECT id,
Sum(issued) AS issued
FROM issuedtbl
WHERE Month(dateissue) = 1 -- Month filter
GROUP BY id) I
ON I.id = M.id
SQL FIDDLE DEMO

sql combine only some duplicates

I want to combine one set of duplicates from my table, but not all.
example:
acct date bal
--------------------
123 1/1/2013 40.00
123 1/1/2013 2.00
456 1/2/2013 50.00
456 1/1/2013 5.00
789 1/1/2013 10.00
789 1/1/2013 17.00
I would like to combine acct 123 to only one row, summing the balance of those rows, but leave the rest.
desired output:
acct date bal
--------------------
123 1/1/2013 42.00
456 1/2/2013 50.00
456 1/1/2013 5.00
789 1/1/2013 10.00
789 1/1/2013 17.00
Working in SQL Server 2005.
Use CASE in GROUP BY clause
SELECT acct, date, SUM(bal) AS bal
FROM dbo.tets73
GROUP BY acct, date, CASE WHEN acct != 123 THEN bal END
Demo on SQLFiddle
SELECT acct, date, SUM(bal)
FROM T
WHERE acct = 123
UNION
SELECT acct, date, bal
FROM T
WHERE acct <> 123
select acct, date, sum(bal) from table where acct = 123
union
select acct, date bal from table where acct <> 123

Update one table based upon SUM(values) in another table on multiple criteria

I can't seem to find out how to do this and not sure exactly how to search for it!
I have a table [MASTER]:
ID varchar(6)
CCY varchar(3)
Val1 decimal(20,5)
Val2 decimal(20,5)
FOO decimal(20,5)
and another table [FOOS]
ID varchar(6)
CCY varchar(3)
Val decimal(20,5)
MASTER contains one row per ID/CCY composite key (not sure if thats correct term) e.g.
ABCDEF GBP 200.00 100.00 null
ABCDEF EUR 400.00 150.00 null
ZYXWVU GBP 300.00 200.00 null
ZYXWVU EUR 400.00 200.00 null
FOOS contains multiple rows and DOES NOT contain a row for every MASTER e.g.
ABCDEF GBP 50.00
ABCDEF GBP 51.00
ABCDEF GBP 150.00
ZYXWVU GBP 100.00
ZYXWVU EUR 200.00
ZYXWVU EUR 400.00
I'd like to run a query to update only matching MASTER rows with SUM(FOOS.Val). e.g.
ABCDEF GBP 200.00 100.00 251.00
ABCDEF EUR 400.00 150.00 null
ZYXWVU GBP 300.00 200.00 100.00
ZYXWVU EUR 400.00 200.00 600.00
...but although I've tried a numer of options (where exists, inner join) I can't seem to be able to either link to a single MASTER or do the SUM(...)
Try this solution:
UPDATE m
SET m.Foo = f.valsum
FROM [MASTER] m
INNER JOIN
(
SELECT ID, CCY, SUM(val) valsum
FROM Foos
GROUP BY ID, CCY
) f ON m.ID = f.ID AND m.CCY = f.CCY;
With postgres, I had to adjust the solution with this to work for me:
UPDATE [MASTER] m
SET Foo = f.valsum
FROM
(
SELECT ID, CCY, SUM(val) valsum
FROM Foos
GROUP BY ID, CCY
) f
WHERE m.ID = f.ID AND m.CCY = f.CCY;
UPDATE accounts SET (contact_last_name, contact_first_name) =
(SELECT last_name, first_name FROM salesmen
WHERE salesmen.id = accounts.sales_id);
update orders
set amount =
(select sum(item_quantity) from order_items
where orders.id = order_items.order_id);