SQL sum of two tables - sql

I have these two tables:
I need to join the payment table with the discount table. The expected output seems not possible since the discounts table doesn't have a payment date. I can only get the net_amount
payment table:
id | net_amount | payment_dt | person_id
1001 | 2765.36 | 2016-05-28 | 372
1002 | 2474.76 | 2016-05-29 | 372
1003 | 22694.25 | 2016-05-29 | 384
1004 | 1911.92 | 2016-05-29 | 384
discounts table:
id | person_id | gross_amount | sc_discount | other_discount_amount | other_discount_type
1 | 372 | 3566.7 | 713.34 | 88.00 | MISC
2 | 372 | 3202.2 | 640.44 | 87.00 | PAT
3 | 384 | 3566.7 | 713.34 | 285.34 | MISC
4 | 384 | 27953.10 | 5590.62 | 2236.25 | PAT
5 | 384 | 2655.45 | 531.09 | 212.44 | MISC
*1 - payment_dt is 2016-05-28
expected output: (where payment_dt=2016-05-29)
total_gross_amount | total_sc_discount | total_misc_discount | total_pat_discount | total_net_amount
37,377.45 | 7475.49 | 497.78 | 2,323.25 | 27,080.93

As I see in both tables common column is person_id, you can try to join with it. And for more information you can have in mind natural joins, read about it on The Internet ;)
"A NATURAL JOIN is a JOIN operation that creates an implicit join clause for you based on the common columns in the two tables being joined. Common columns are columns that have the same name in both tables. A NATURAL JOIN can be an INNER join, a LEFT OUTER join, or a RIGHT OUTER join. The default is INNER join. "

By assuming :
net_amount = gross_amount - sc_discount - other_discount_amount
You do not need to go to payments table for total_net_amount in the expected output
You can write it like this :
Select sum(gross_amount) as total_gross_amount,
sum(sc_discount) as total_sc_discount,
sum(gross_amount - sc_discount - other_discount_amount) as total_net_amount
sum(CASE other_discount_type when 'MISC' THEN other_discount_amount WHEN 'PAT' THEN 0) as total_misc_discount,
sum(CASE other_discount_type when 'MISC' THEN 0 WHEN 'PAT' THEN other_discount_amount) as total_pat_discount
from discounts
And in case the above assumption is not true, As the aggregation is complete, only 1 row will come in output, you can get all columns except total_net_amount as in above query, get sum(net_amount) from payments table, and join them on true as only 1,1 row.

Related

SQL Multiple Joining

I'm trying to join the two table and at the same time getting the value of the certain column by using inner join, I tried joining until the 3rd diagram but when it comes to the fourth it doesn't display the null values, how can I display the values of the 4th column even the null values
here's the code of the SQL
betl.user_id,
betl.agent_id,
ah1.parent_id,
ah2.user_id,
ah3.user_id AS parent_of_agent
FROM
wpc16_02.bets_logs betl
INNER JOIN
wpc16_02.agent_heirarchy ah1 ON betl.agent_id = ah1.user_id
INNER JOIN
wpc16_02.agent_heirarchy ah2 ON ah1.parent_id = ah2.id
INNER JOIN
wpc16_02.agent_heirarchy ah3 ON ah2.parent_id = ah3.id
WHERE
fight_id = 1930 AND agent_income = 0
here's what I'm trying to achieve by using innerjoins:
Here's the result I got when trying the joining upto the 3rd diagram:
user_id | agent_id | parent_id | user_id_of_parent
15012 | 2212 | 96 | 160
227097 | 22061 | 266 | 64
465174 | 464899 | 126 | 211
505094 | 504767 | 980 | 5358
241158 | 8281 | 18 | 67
463344 | 462715 | 751 | 3420
184396 | 29870 | 502 | 2123
486847 | 43225 | 164 | 234
482120 | 482023 | 4430 | 46469
369628 | 217212 | 8283 | 109697
When joining upto 4th diagram:
user_id | agent_id | parent_id | user_id_of_parent | master_uid
184396 | 29870 | 502 | 2123 | 160
482120 | 482023 | 4430 | 46469 | 699
369628 | 217212 | 8283 | 109697 | 71
97287 | 93996 | 7332 | 93866 | 3114
113287 | 113228 | 2714 | 20652 | 4050
366287 | 361918 | 17603 | 235880 | 234
439935 | 236147 | 3776 | 40054 | 103
480201 | 436936 | 1041 | 5761 | 160
456400 | 456248 | 32901 | 431900 | 240
502877 | 497592 | 2571 | 20845 | 3918
notice the other datas have been removed because when I joined the 4th diagram some of the results are null
You seem to want LEFT JOIN. It is a little unclear what the exact query is, because your question doesn't have information such as which columns are in which tables.
But the idea is:
SELECT . . .
FROM wpc16_02.bets_logs betl LEFT JOIN
wpc16_02.agent_heirarchy ah1
ON betl.agent_id = ah1.user_id LEFT JOIN
wpc16_02.agent_heirarchy ah2
ON ah1.parent_id = ah2.id LEFT JOIN
wpc16_02.agent_heirarchy ah3
ON ah2.parent_id = ah3.id
WHERE betl.fight_id = 1930 AND betl.agent_income = 0
This assums that flight_id and agent_income are from the first table. If they are in one of the hierarchy tables, then the conditions should go in the appropriate ON clause.

Returning singular row/value from joined table date based on closest date

I have a Production Table and a Standing Data table. The relationship of Production to Standing Data is actually Many-To-Many which is different to how this relationship is usually represented (Many-to-One).
The standing data table holds a list of tasks and the score each task is worth. Tasks can appear multiple times with different "ValidFrom" dates for changing the score at different points in time. What I am trying to do is query the Production Table so that the TaskID is looked up in the table and uses the date it was logged to check what score it should return.
Here's an example of how I want the data to look:
Production Table:
+----------+------------+-------+-----------+--------+-------+
| RecordID | Date | EmpID | Reference | TaskID | Score |
+----------+------------+-------+-----------+--------+-------+
| 1 | 27/02/2020 | 1 | 123 | 1 | 1.5 |
| 2 | 27/02/2020 | 1 | 123 | 1 | 1.5 |
| 3 | 30/02/2020 | 1 | 123 | 1 | 2 |
| 4 | 31/02/2020 | 1 | 123 | 1 | 2 |
+----------+------------+-------+-----------+--------+-------+
Standing Data
+----------+--------+----------------+-------+
| RecordID | TaskID | DateActiveFrom | Score |
+----------+--------+----------------+-------+
| 1 | 1 | 01/02/2020 | 1.5 |
| 2 | 1 | 28/02/2020 | 2 |
+----------+--------+----------------+-------+
I have tried the below code but unfortunately due to multiple records meeting the criteria, the production data duplicates with two different scores per record:
SELECT p.[RecordID],
p.[Date],
p.[EmpID],
p.[Reference],
p.[TaskID],
s.[Score]
FROM ProductionTable as p
LEFT JOIN StandingDataTable as s
ON s.[TaskID] = p.[TaskID]
AND s.[DateActiveFrom] <= p.[Date];
What is the correct way to return the correct and singular/scalar Score value for this record based on the date?
You can use apply :
SELECT p.[RecordID], p.[Date], p.[EmpID], p.[Reference], p.[TaskID], s.[Score]
FROM ProductionTable as p OUTER APPLY
( SELECT TOP (1) s.[Score]
FROM StandingDataTable AS s
WHERE s.[TaskID] = p.[TaskID] AND
s.[DateActiveFrom] <= p.[Date]
ORDER BY S.DateActiveFrom DESC
) s;
You might want score basis on Record Level if so, change the where clause in apply.

Joining Two SQL Tables on Different Databases [duplicate]

This question already has answers here:
Can we use join for two different database tables?
(2 answers)
Closed 4 years ago.
I have two tables on two separate databases. We will call them Table1 and Table2.
Table1:
+----------+----------+----------+---------+------+----------+
| UniqueID | Date1 | Date2 | Fruit | Cost | Duration |
+----------+----------+----------+---------+------+----------+
| 1 | 09/10/18 | 10/20/18 | Apples | 1.50 | 7 |
| 2 | 09/18/18 | 10/25/18 | Oranges | 1.75 | 10 |
| 3 | 10/01/18 | 10/30/18 | Bananas | 2.00 | 10 |
+----------+----------+----------+---------+------+----------+
Table2:
+----------+---------+------+----------+-----------+
| Date1 | Fruit | Cost | Duration | New Price |
+----------+---------+------+----------+-----------+
| 09/10/18 | Savory | 1.50 | 7 | 1.90 |
| 09/18/18 | Citrusy | 1.75 | 10 | 2.50 |
| 10/01/18 | Mealy | 2.00 | 10 | 2.99 |
| 10/20/18 | Savory | 1.50 | 7 | 3.90 |
| 10/25/18 | Citrusy | 1.75 | 10 | 4.50 |
| 10/30/18 | Mealy | 2.00 | 10 | 5.99 |
+----------+---------+------+----------+-----------+
What I need the output to look like:
+----------+----------+--------------------+----------+--------------------+
| UniqueID | Date1 | New Price on Date1 | Date2 | New Price on Date2 |
+----------+----------+--------------------+----------+--------------------+
| 1 | 09/10/18 | 1.90 | 10/20/18 | 3.90 |
| 2 | 09/18/18 | 2.50 | 10/25/18 | 4.50 |
| 3 | 10/01/18 | 2.99 | 10/30/18 | 5.99 |
+----------+----------+--------------------+----------+--------------------+
I need to first convert table1.fruit to the representation of table2.fruit (apples-->savory, oranges-->citrusy, bananas-->mealy) then join on table1.fruit = table2.fruit, table1.duration = table2.duration, table1.cost = table2.cost, table1.date1 = table2.date1, and table1.date2 = table2.date1.
I don't know where to start on writing the statement. I looked over some previous questions posted here, but they really just go over the basics of linking two tables from different databases. Do I convert the table1.fruit first in the select statement, then join, or do I convert table1.fruit in the join statement? How do I join table2.date1 on both table1.date1 and table1.date2 to get the price associated with both dates?
If I can provide any more information for you, please let me know.
I am on SQL Server 2017 using Management Studio.
Thanks for any help in advance!
Create a mapping table to bridge between the different codes for fruits.
IF OBJECT_ID('tempdb..#FruitMappings') IS NOT NULL
DROP TABLE #FruitMappings
CREATE TABLE #FruitMappings (
Table1Fruit VARCHAR(100),
Table2Fruit VARCHAR(100))
INSERT INTO #FruitMappings (
Table1Fruit,
Table2Fruit)
VALUES
('Apples', 'Savory'),
('Oranges', 'Citrusy'),
('Bananas', 'Mealy')
SELECT
T1.*
--, whichever columns you need
FROM
Database1.Schema1.Table1 AS T1
INNER JOIN #FruitMappings AS F ON T1.Fruit = F.Table1Fruit
INNER JOIN Database2.Schema2.Table2 AS T2 ON
F.Table2Fruit = T2.Fruit AND
T1.Cost = T2.Cost AND
T1.Duration = T2.Duration
-- AND any other matches you need
You can use LEFT JOIN or even FULL JOIN, depending if you might have some fruits on a table that aren't available on the other (careful with NULL values if FULL JOIN).
If both databases are on the same SQL Server instance and your SQL Server login has access to both databases you can just use the full form of the object names:
select * -- Whatever...
from Database1.dbo.Table1 t1
inner join Database2.dbo.Table2 t2
on t1,UniqueId = t2.UniqueId -- Or whatever your join condition is
(adding where etc. clauses as required.)
This assumes both databases are using the default schema, otherwise replace dbo as necessary.
If the databases are on different servers you can use linked servers, but there are performance implications (the whole remote table may be read because the optimiser can't do much to filter it).

Joining three tables with primary in the middle

I am breaking my head on joining of three tables. I have recreated a simple test case where I see the same problem, so it looks I make a fundamental mistake in my join query:
I have three tables:
case:
id (PK)| date_closed
155 | '2018-04-17 10:08'
156 | '2018-03-17 10:08'
pizza | '2018-02-17 10:08'
registration:
id (FK) | source | quantity
155 | market | 300
155 | sawdust| 200
bagged:
id | case_id (FK) | kg_bagged
X | 155 | 123
Y | 155 | 90
These tables I want to join to compare the total amounts per 'case' in quantity column and kg_bagged. So the case table has a 1:* many relationship to the other two. Therefore I make a join query like this:
SELECT case.id,
date_closed,
SUM(quantity),
SUM(kg_bagged),
SUM(kg_bagged)/SUM(quantity) AS reduction_factor
FROM case
JOIN bagged ON case.id = bagged.case_id
JOIN registration ON case.id = registration.id
Than I would think this would be a correct query, but Postgres tells me I have to add case.id, date_closed to the group by clause. So I add this:
GROUP BY case.id, date_closed;
This code is running without errors, but it shows 1000 for the quanity at case 155 not the expected 500 (200+300). This behaviour only appears when there is more than 1 record. When joining only 1 table to the case table it also works fine. Can someone see the mistake made at the JOIN query?
I also tried using a subquery for joining two tables and than use a join on the table left, but it gave me similar results
When you joining data 2 rows on 2 other tables it match together, so you get the multiplied result. In your example is 2*2 = 4
For easier understand, in your case when you execute the query
SELECT case.id, date_closed, source, quantity, kg_bagged
FROM case
JOIN registration ON registration.id = case.id
JOIN bagged ON bagged.case_id = case.id
You will get the data like this:
| id | date_closed | source | quantity | kg_bagged |
| :-: | :----------------: | :----: | :------: | :-------: |
| 155 | '2018-04-17 10:08' | market | 300 | 123 |
| 155 | '2018-04-17 10:08' | sawdust| 200 | 123 |
| 155 | '2018-04-17 10:08' | market | 300 | 90 |
| 155 | '2018-04-17 10:08' | sawdust| 200 | 90 |
In this case, as my experience before, I used to write subquery first to get the sum data first then joining it together.
Such as:
WITH r AS (SELECT id, sum(quantity) as quantity FROM registration GROUP BY id),
b as (SELECT case_id, SUM(kg_bagged) as kg_bagged FROM bagged GROUP BY case_id)
SELECT case.id,
date_closed,
quantity,
kg_bagged,
kg_bagged/quantity AS reduction_factor
FROM case
JOIN b ON case.id = b.case_id
JOIN r ON case.id = r.id
Hopefully, this answer will help you.

Four Table Join in BigQuery

Okay, so I'm trying to link together four different tables, and its getting very difficult. I provided snippets of each table in the hopes you all could help out
Table 1: data
+--------+--------+-----------+
| charge | amount | date |
+--------+--------+-----------+
| 123 | 10000 | 2/10/2016 |
| 456 | 10000 | 1/28/2016 |
| 789 | 10000 | 3/30/2016 |
+--------+--------+-----------+
Table 2: data_metadata
+--------+------------+------------+
| charge | key | value |
+--------+------------+------------+
| 123 | identifier | trrkfll212 |
| 456 | code | test |
| 789 | ID | 123xyz |
+--------+------------+------------+
Table 3: buyer
+-----+-----------+----------+----------+
| id | date | discount | plan |
+-----+-----------+----------+----------+
| ABC | 2/13/2016 | yes | option a |
| DEF | 2/1/2016 | yes | option a |
| GHI | 1/22/2016 | no | option a |
+-----+-----------+----------+----------+
Table 4: buyer_metadata
+--------------+-----------+--------+
| id | |key| | value |
+--------------+-----------+--------+
| ABC | migration | TRUE |
| DEF | emid | foo |
| GHI | ID | 123xyz |
+--------------+-----------+--------+
Okay, so the tables data and data_metadata are obviously connected by the charge column.
The tables buyer and buyer_metadata are connected by the id column.
But I want to link all of them together. I'm pretty sure the way to accomplish this is through linking the metadata tables together through the common field in the "value" column (in this example: 123xyz).
Could anyone help?
This might look like something like that if all "link" columns are unique :
SELECT *
FROM data d
JOIN data_metadata dm ON d.charge = dm.charge
JOIN buyer_metada bm ON dm.value = bm.value
JOIN buyer b ON bm.id = b.id
If not, I think you'll have to use something like GROUP BY clause
Let's take it in two steps, first create composite tables for data and buyer. Composite table for data:
SELECT data.charge, data.amount, data.date,
data_metadata.key, data_metadata.value
FROM [data] AS data
JOIN (SELECT charge, key, value FROM [data_metadata]) AS data_metadata
ON data.charge = data_metadata.charge
And composite table for buyer:
SELECT buyer.id, buyer.date, buyer.discount, buyer.plan,
buyer_metadata.key, buyer_metadata.value
FROM [buyer] AS buyer
JOIN (SELECT key, value FROM [buyer_metadata]) AS buyer_metadata
ON buyer.id = buyer_metadata.id
And then let's join the two composite tables
SELECT composite_data.*, composite_buyer.*
FROM (
SELECT data.charge, data.amount, data.date,
data_metadata.key, data_metadata.value
FROM [data] AS data
JOIN (SELECT charge, key, value FROM [data_metadata]) AS data_metadata
ON data.charge = data_metadata.charge) AS composite_data
JOIN (
SELECT buyer.id, buyer.date, buyer.discount, buyer.plan,
buyer_metadata.key, buyer_metadata.value
FROM [buyer] AS buyer
JOIN (SELECT key, value FROM [buyer_metadata]) AS buyer_metadata
ON buyer.id = buyer_metadata.id) AS composite_buyer
ON composite_data.value = composite_buyer.value
I haven't tested it but it's probably close.
For reference, here is the page on BigQuery JOINs. And have you seen this SO?