Get aggregate quantity from JOINED tables - sql

I have the following two tables in my database
inventory_transactions table
id | date_created | company_id | product_id | quantity | amount | is_verified | buy_or_sell_to | transaction_type | parent_tx | invoice_id | order_id | transaction_comment
----+----------------------------+------------+------------+----------+--------+-------------+----------------+------------------+-----------+------------+----------+---------------------
1 | 2022-04-25 10:42:00.627495 | 20 | 100 | 23 | 7659 | t | | BUY | | 1 | |
2 | 2022-04-25 10:48:48.02342 | 21 | 2 | 10 | 100 | t | | BUY | | 2 | |
3 | 2022-04-25 11:00:11.624176 | 21 | 7 | 10 | 100 | t | | BUY | | 3 | |
4 | 2022-04-25 11:08:14.607117 | 23 | 1 | 11 | 1210 | t | | BUY | | 4 | |
5 | 2022-04-25 11:13:24.084845 | 23 | 28 | 16 | 2560 | t | | BUY | | 5 | |
6 | 2022-04-25 11:26:56.338881 | 23 | 28 | 15 | 3525 | t | 5 | BUY | | 6 | 1 |
7 | 2022-04-25 11:26:56.340112 | 5 | 28 | 15 | 3525 | t | 23 | SELL | 6 | 6 | 1 |
8 | 2022-04-25 11:30:08.529288 | 23 | 30 | 65 | 15925 | t | 5 | BUY | | 7 | 2 |
9 | 2022-04-25 11:30:08.531005 | 5 | 30 | 65 | 15925 | t | 23 | SELL | 8 | 7 | 2 |
14 | 2022-04-25 12:28:51.658902 | 23 | 28 | 235 | 55225 | t | 5 | BUY | | 11 | 5 |
15 | 2022-04-25 12:28:51.660478 | 5 | 28 | 235 | 55225 | t | 23 | SELL | 14 | 11 | 5 |
20 | 2022-04-25 13:01:31.091524 | 20 | 4 | 4 | 176 | t | | BUY | | 15 | |
10 | 2022-04-25 11:50:48.4519 | 21 | 38 | 1 | 10 | t | | BUY | | 8 | |
11 | 2022-04-25 11:50:48.454118 | 21 | 36 | 1 | 10 | t | | BUY | | 8 | |
12 | 2022-04-25 11:52:19.827671 | 21 | 29 | 1 | 10 | t | | BUY | | 9 | |
13 | 2022-04-25 11:53:16.699881 | 21 | 74 | 1 | 10 | t | | BUY | | 10 | |
16 | 2022-04-25 12:37:39.739125 | 20 | 1 | 228 | 58824 | t | | BUY | | 12 | |
17 | 2022-04-25 12:37:39.741106 | 20 | 3 | 228 | 58824 | t | | BUY | | 12 | |
18 | 2022-04-25 12:49:09.922686 | 21 | 41 | 10 | 1000 | t | | BUY | | 13 | |
19 | 2022-04-25 12:55:11.986451 | 20 | 5 | 22 | 484 | t | | BUY | | 14 | |
NOTE each transaction in the inventory_transactions table is recorded twice with the company_id and buy_or_sell_to swapped for the 2nd row and transaction_type BUY or SELL reserved. (similar to how a journal is menatained in accounting).
db# select * from inventory_transactions where buy_or_sell_to is not Null order by date_created limit 50;
id | date_created | company_id | product_id | quantity | amount | is_verified | buy_or_sell_to | transaction_type | parent_tx | invoice_id | order_id | transaction_comment
----+----------------------------+------------+------------+----------+--------+-------------+----------------+------------------+-----------+------------+----------+---------------------
6 | 2022-04-25 11:26:56.338881 | 23 | 28 | 15 | 3525 | t | 5 | BUY | | 6 | 1 |
7 | 2022-04-25 11:26:56.340112 | 5 | 28 | 15 | 3525 | t | 23 | SELL | 6 | 6 | 1 |
8 | 2022-04-25 11:30:08.529288 | 23 | 30 | 65 | 15925 | t | 5 | BUY | | 7 | 2 |
9 | 2022-04-25 11:30:08.531005 | 5 | 30 | 65 | 15925 | t | 23 | SELL | 8 | 7 | 2 |
companies table (consider this as the users table, in my project all users are companies)
id | company_type | gstin | name | phone_no | address | pincode | is_hymbee_verified | is_active | district_id | pancard_no
----+--------------+-----------------+-------------+------------+---------+---------+--------------------+-----------+-------------+------------
26 | RETAILER | XXXXXXXXXXXXXXX | ACD LLC | 12345%7898 | AQWSAQW | 319401 | | | 11 | AQWSDERFVV
27 | DISTRIBUTOR | XXXXXXXXXXXXXXX | CDF LLC | 123XX7898 | AGWSAQW | 319201 | | | 13 | AQWSDERFVV
28 | RETAILER | XXXXXXXXXXXXXXX | !## LLC | 1234!67XX9 | AQCCAQW | 319101 | | | 16 | AQWSDERFVV
29 | COMPANY | XXXXXXXXXXXXXXX | ZAZ LLC | 123456S898 | AQWQQQW | 319001 | | | 19 | AQWSDERFVV
Problem statement
The query I am trying to write will fetch quantity sold only to users who are RETAILERs and DISTRIBUTORS by users who are either a RETAILER or a DISTRIBUTOR.
for example, if a user is a RETAILER, we need to calculate how much quantity this RETAILER has sold to other users who are either RETAILER or DISTRIBUTORs.
In other words, for all rows in the companies table check if the company is of company_type, RETAILER or DISTRIBUTOR and from the inventory_transactions table, check how much quantity a partiuclar RETAILER OR DISTRIBUTOR has sold to other RETAILERs and DISTRIBUTORs
I have very basic knowledge of SQL and have only gotten so far:
select Seller.id as Seller_ROW, Buyer.id as Buyer_row, Seller.company_id, Buyer.buy_or_sell_to, Seller.company_type as Seller_Type, Buyer.company_type as Buyer_Type, Seller.quantity, Buyer.quantity
FROM
(select t.id, t.company_id, t.quantity, c.company_type
from inventory_transactions as t
join companies as c on c.id = t.company_id
where c.company_type = 'RETAILER' or company_type = 'DISTRIBUTOR'
) as Seller
JOIN
(select t.id, t.buy_or_sell_to, t.quantity, c.company_type
from inventory_transactions as t
join companies as c on c.id = t.buy_or_sell_to
where c.company_type = 'RETAILER' or company_type = 'DISTRIBUTOR') as Buyer on Seller.id = Buyer.id
output
seller_row | buyer_row | company_id | buy_or_sell_to | seller_type | buyer_type | quantity | quantity
------------+-----------+------------+----------------+-------------+-------------+----------+----------
25 | 25 | 22 | 25 | RETAILER | DISTRIBUTOR | 1 | 1
26 | 26 | 25 | 22 | DISTRIBUTOR | RETAILER | 1 | 1
31 | 31 | 37 | 43 | DISTRIBUTOR | RETAILER | 10 | 10
32 | 32 | 43 | 37 | RETAILER | DISTRIBUTOR | 10 | 10
33 | 33 | 21 | 43 | DISTRIBUTOR | RETAILER | 1 | 1
34 | 34 | 43 | 21 | RETAILER | DISTRIBUTOR | 1 | 1
35 | 35 | 21 | 49 | DISTRIBUTOR | RETAILER | 1 | 1
36 | 36 | 49 | 21 | RETAILER | DISTRIBUTOR | 1 | 1
37 | 37 | 21 | 51 | DISTRIBUTOR | RETAILER | 1 | 1
38 | 38 | 51 | 21 | RETAILER | DISTRIBUTOR | 1 | 1
There are duplicate rows in the resulting table and so i am unable to do a SUM().
Expected result
SELLER.company_id | SELLER.company_name | SELLER.company_type | QUANTITY | BUYER.company_type
26 | XYZ Retail Co. | RETAILER | 14 | RETAILER
26 | XYZ Retail Co. | RETAILER | 1 | DISTRIBUTOR
27 | ACD Distributions | DISTRIBUTOR | 0 | RETAILER
27 | ACD Distributions | DISTRIBUTOR | 10 | DISTRIBUTOR

This answer assumes that every sale is represented as two rows in inventory_transactions, which makes it possible to avoid duplicates by working with only one transaction_type, so we'll filter on SELL transactions.
SELECT t.company_id AS seller_company_id
, s.company_name AS seller_company_name
, s.company_type AS seller_company_type
, SUM(t.quantity) AS quantity
, b.company_type AS buyer_company_type
FROM inventory_transactions AS t
INNER JOIN companies AS s
ON s.id = t.company_id
INNER JOIN companies AS b
ON b.id = buy_or_sell_to
WHERE t.transaction_type = 'SELL'
AND s.company_type IN ('RETAILER','DISTRIBUTOR')
AND b.company_type IN ('RETAILER','DISTRIBUTOR')
GROUP BY t.company_id, s.company_name, s.company_type, b.company_type
ORDER BY seller_company_id, seller_company_name, seller_company_type, buyer_company_type
;

Related

PostgreSQL: Count number of rows in table 1 for distinct rows in table 2

I am working with really big data that at the moment I become confused, looking like I'm just repeating one thing.
I want to count the number of trips per user from two tables, trips and session.
psql=> SELECT * FROM trips limit 10;
trip_id | session_ids | daily_user_id | seconds_start | seconds_end
---------+-----------------+---------------+---------------+-------------
400543 | {172079} | 17118 | 1575550944 | 1575551181
400542 | {172078} | 17118 | 1575541533 | 1575542171
400540 | {172077} | 17118 | 1575539001 | 1575539340
400538 | {172076} | 17117 | 1575540499 | 1575541999
400534 | {172074,172075} | 17117 | 1575537161 | 1575539711
400530 | {172073} | 17116 | 1575447043 | 1575447682
400529 | {172071} | 17115 | 1575496394 | 1575497803
400527 | {172070} | 17113 | 1575495241 | 1575496034
400525 | {172068} | 17115 | 1575485658 | 1575489378
400524 | {172067} | 17113 | 1575488721 | 1575490491
(10 rows)
psql=> SELECT * FROM session limit 10;
session_id | user_id | key | start_time | daily_user_id
------------+---------+--------------------------+------------+---------------
172079 | 43 | hLB8S7aSfp4gAFp7TykwYQ==+| 1575550921 | 17118
| | | |
172078 | 43 | YATMrL/AQ7Nu5q2dQTMT1A==+| 1575541530 | 17118
| | | |
172077 | 43 | fOLX4tqvsyFOP3DCyBZf1A==+| 1575538997 | 17118
| | | |
172076 | 7 | 88hwGj4Mqa58juy0PG/R4A==+| 1575540515 | 17117
| | | |
172075 | 7 | 1O+8X49+YbtmoEa9BlY5OQ==+| 1575538384 | 17117
| | | |
172074 | 7 | XOR7hsFCNk+soM75ZhDJyA==+| 1575537405 | 17117
| | | |
172073 | 42 | rAQWwYgqg3UMTpsBYSpIpA==+| 1575447109 | 17116
| | | |
172072 | 276 | 0xOsxRRN3Sq20VsXWjlrzQ==+| 1575511120 | 17114
| | | |
172071 | 7 | P4beN3W/ZrD+TCpZGYh23g==+| 1575496642 | 17115
| | | |
172070 | 43 | OFi30Zv9e5gmLZS5Vb+I7Q==+| 1575495238 | 17113
| | | |
(10 rows)
Goal: get the distribution of trips per user
Attempt:
psql=> SELECT COUNT(distinct trip_id) as trips
, count(distinct user_id) as users
, extract(year from to_timestamp(seconds_start)) as year_date
, extract(month from to_timestamp(seconds_start)) as month_date
FROM trips
INNER JOIN session
ON session_id = ANY(session_ids)
GROUP BY year_date, month_date
ORDER BY year_date, month_date;
+-------+-------+-----------+------------+
| trips | users | year_date | month_date |
+-------+-------+-----------+------------+
| 371 | 44 | 2016 | 3 |
| 12207 | 185 | 2016 | 4 |
| 3859 | 88 | 2016 | 5 |
| 1547 | 28 | 2016 | 6 |
| 831 | 17 | 2016 | 7 |
| 427 | 4 | 2016 | 8 |
| 512 | 13 | 2016 | 9 |
| 431 | 11 | 2016 | 10 |
| 1011 | 26 | 2016 | 11 |
| 791 | 15 | 2016 | 12 |
| 217 | 8 | 2017 | 1 |
| 490 | 17 | 2017 | 2 |
| 851 | 18 | 2017 | 3 |
| 1890 | 66 | 2017 | 4 |
| 2143 | 43 | 2017 | 5 |
| . | | | |
| . | | | |
| . | | | |
+-------+-------+-----------+------------+
This resultset count number of users and trips, my intention is actually to get an analysis of trips per user, like so:
+------+-------------+
| user | no_of_trips |
+------+-------------+
| 1 | 489 |
| 2 | 400 |
| 3 | 12 |
| 4 | 102 |
| . | |
| . | |
| . | |
+------+-------------+
How do I do this, please?
You seem to just want aggregation by user_id:
SELECT s.user_id, COUNT(distinct t.trip_id) as trips
FROM trips t INNER JOIN
session s
ON s.session_id = ANY(t.session_ids)
GROUP BY s.user_id ;
I'm pretty sure that the COUNT(DISTINCT) is unnecessary, so I would advise removing it:
SELECT s.user_id, COUNT(*) as trips
FROM trips t INNER JOIN
session s
ON s.session_id = ANY(t.session_ids)
GROUP BY s.user_id ;

How to select data order by sort value and sort NULL By name

I wrote following SQL query to select data from #tmp table variable.
SELECT #rowCount AS [row-count],
t.[row-no] AS [row-no],
t.[ServiceID] AS ServiceID,
t.ServiceName AS ServiceName,
t.[BranchServiceSortValue] AS SortValue,
(CASE WHEN t.OptIn = 1 THEN 'Yes' ELSE 'No' END) AS OptIn
FROM #tmp t
INNER JOIN dbo.Category
ON Category.CategoryId = t.FkCategoryId
INNER JOIN dbo.ServiceType
ON ServiceType.ServiceTypeId = t.FkServiceTypeId
WHERE t.[row-no] >= #startRow
AND t.[row-no] <= #endRow
ORDER BY t.BranchServiceSortValue,t.serviceName
According to the data in #tmp table,my above query return following output.
| row-count | row-no | ServiceID | ServiceName | SortValue | OptIn |
|-----------|--------|-----------|-------------|-----------|-------|
| 24 | 4 | 1088 | AAB | NULL | No |
| 24 | 5 | 1089 | AAC | NULL | No |
| 24 | 6 | 1090 | AAD | NULL | No |
| 24 | 1 | 1093 | GDGD | 0 | Yes |
| 24 | 7 | 1091 | EETETE | 1 | Yes |
| 24 | 8 | 1092 | CSCDF | 2 | Yes |
| 24 | 3 | 1086 | CXCX | 3 | Yes |
| 24 | 9 | 16 | ASA | 4 | Yes |
| 24 | 2 | 1087 | BFB | 5 | Yes |
| 24 | 10 | 7 | Mortgage | 6 | Yes |
| 24 | 11 | 17 | DDWW | 7 | Yes |
| 24 | 12 | 11 | IL | 8 | Yes |
| 24 | 13 | 5 | SAA | 9 | Yes |
| 24 | 14 | 9 | CD | 10 | Yes |
You can see according to my above query data rows are sorted by SortValue and when SortValue = NULL, those 3 rows sorted by its ServiceName,
But I need to displaySortValue = NULLrows at the bottom of the other rows.Its mean I need to display Null rows after the SortValue Not NULL data and SortValue = NULL should be display order by its ServiceName.
My Expected Output is:
| row-count | row-no | ServiceID | ServiceName | SortValue | OptIn |
|-----------|--------|-----------|-------------|-----------|-------|
| 14 | 1 | 1093 | GDGD | 0 | Yes |
| 14 | 7 | 1091 | EETETE | 1 | Yes |
| 14 | 8 | 1092 | CSCDF | 2 | Yes |
| 14 | 3 | 1086 | CXCX | 3 | Yes |
| 14 | 9 | 16 | ASA | 4 | Yes |
| 14 | 2 | 1087 | BFB | 5 | Yes |
| 14 | 10 | 7 | Mortgage | 6 | Yes |
| 14 | 11 | 17 | DDWW | 7 | Yes |
| 14 | 12 | 11 | IL | 8 | Yes |
| 14 | 13 | 5 | SAA | 9 | Yes |
| 14 | 14 | 9 | CD | 10 | Yes |
| 14 | 4 | 1088 | AAB | NULL | No |
| 14 | 5 | 1089 | AAC | NULL | No |
| 14 | 6 | 1090 | AAD | NULL | No |
How should I need to change my query to get above output? please help me
NULL has the lowest value, so you'll need to use a CASE to put NULL at the end, and then sort by SortValue:
ORDER BY CASE WHEN t.BranchServiceSortValue IS NULL THEN 1 ELSE 0 END,
t.BranchServiceSortValue,
t.serviceName;
Just add a key to the ORDER BY:
ORDER BY (CASE WHEN t.BranchServiceSortValue IS NOT NULL THEN 1 ELSE 2 END),
t.BranchServiceSortValue, t.serviceName
The SQL standard provides the options NULLS FIRST and NULLS LAST for ORDER BY clauses. SQL Server does not (yet) implement these.

Pandas - Grouping Rows With Same Value in Dataframe

Here is the dataframe in question:
|City|District|Population| Code | ID |
| A | 4 | 2000 | 3 | 21 |
| A | 8 | 7000 | 3 | 21 |
| A | 38 | 3000 | 3 | 21 |
| A | 7 | 2000 | 3 | 21 |
| B | 34 | 3000 | 6 | 84 |
| B | 9 | 5000 | 6 | 84 |
| C | 4 | 9000 | 1 | 28 |
| C | 21 | 1000 | 1 | 28 |
| C | 32 | 5000 | 1 | 28 |
| C | 46 | 20 | 1 | 28 |
I want to regroup the population counts by city to have this kind of output:
|City|Population| Code | ID |
| A | 14000 | 3 | 21 |
| B | 8000 | 6 | 84 |
| C | 15020 | 1 | 28 |
df = df.groupby(['City', 'Code', 'ID'])['Population'].sum()
You can make a group by 'City', 'Code' and 'ID then make sum of 'population'.

Why do you need to include a field in GROUP BY when using OVER (PARTITION BY x)?

I have a table for which I want to do a simple sum of a field, grouped by two columns. I then want the total for all values for each year_num.
See example: http://rextester.com/QSLRS68794
This query is throwing: "42803: column "foo.num_cust" must appear in the GROUP BY clause or be used in an aggregate function", and I cannot figure out why. Why would an aggregate function using the OVER (PARTITION BY x) require the summed field to be in GROUP BY??
select
year_num
,age_bucket
,sum(num_cust)
--,sum(num_cust) over (partition by year_num) --THROWS ERROR!!
from
foo
group by
year_num
,age_bucket
order by 1,2
TABLE:
| loc_id | year_num | gen | cust_category | cust_age | num_cust | age_bucket |
|--------|-----------|------|----------------|-----------|-----------|-------------|
| 1 | 2016 | M | cash | 41 | 2 | 04_<45 |
| 1 | 2016 | F | Prepaid | 41 | 1 | 03_<35 |
| 1 | 2016 | F | cc | 61 | 1 | 05_45+ |
| 1 | 2016 | F | cc | 19 | 2 | 02_<25 |
| 1 | 2016 | M | cc | 64 | 1 | 05_45+ |
| 1 | 2016 | F | cash | 46 | 1 | 05_45+ |
| 1 | 2016 | F | cash | 27 | 3 | 03_<35 |
| 1 | 2016 | M | cash | 42 | 1 | 04_<45 |
| 1 | 2017 | F | cc | 35 | 1 | 04_<45 |
| 1 | 2017 | F | cc | 37 | 1 | 04_<45 |
| 1 | 2017 | F | cash | 46 | 1 | 05_45+ |
| 1 | 2016 | F | cash | 19 | 4 | 02_<25 |
| 1 | 2017 | M | cash | 43 | 1 | 04_<45 |
| 1 | 2017 | M | cash | 29 | 1 | 03_<35 |
| 1 | 2016 | F | cc | 13 | 1 | 01_<18 |
| 1 | 2017 | F | cash | 16 | 2 | 01_<18 |
| 1 | 2016 | F | cc | 17 | 2 | 01_<18 |
| 1 | 2016 | M | cc | 17 | 2 | 01_<18 |
| 1 | 2017 | F | cash | 18 | 9 | 02_<25 |
DESIRED OUTPUT:
| year_num | age_bucket | sum | sum over (year_num) |
|----------|------------|-----|---------------------|
| 2016 | 01_<18 | 5 | 21 |
| 2016 | 02_<25 | 6 | 21 |
| 2016 | 03_<35 | 4 | 21 |
| 2016 | 04_<45 | 3 | 21 |
| 2016 | 05_45+ | 3 | 21 |
| 2017 | 01_<18 | 2 | 16 |
| 2017 | 02_<25 | 9 | 16 |
| 2017 | 03_<35 | 1 | 16 |
| 2017 | 04_<45 | 3 | 16 |
| 2017 | 05_45+ | 1 | 16 |
You need to nest the sum()s:
select year_num, age_bucket, sum(num_cust),
sum(sum(num_cust)) over (partition by year_num) --WORKS!!
from foo
group by year_num, age_bucket
order by 1, 2;
Why? Well, the window function is not doing aggregation. The argument needs to be an expression that can be evaluated after the group by (because this is an aggregation query). Because num_cust is not a group by key, it needs an aggregation function.
Perhaps this is clearer if you used a subquery:
select year_num, age_bucket, sum_num_cust,
sum(sum_num_cust) over (partition by year_num)
from (select year_num, age_bucket, sum(num_cust) as sum_num_cust
from foo
group by year_num, age_bucket
) ya
order by 1, 2;
These two queries do exactly the same thing. But with the subquery it should be more obvious why you need the extra aggregation.

How can I do this in SQL in a Single Statement?

I have the following MySQL table:
+---------+------------+------+--------+------+---------+------------+-------+---------+----------+------------+------------+
| Version | Yr_Varient | FY | Period | CoA | Company | Item | Mvt | Ptnr_Co | Investee | GC | LC |
+---------+------------+------+--------+------+---------+------------+-------+---------+----------+------------+------------+
| 201 | 1 | 2010 | 1 | 11 | 23 | 1110105000 | 60200 | | | 450000 | 450000 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 2110300000 | 60200 | | | -520000 | -520000 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 1220221600 | | | | 78080 | 78080 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 2130323000 | | | | 50000 | 50000 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 2130322000 | | | | -58080 | -58080 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 3100505000 | | | | -275000 | -275000 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 3200652500 | | | | 216920 | 216920 |
| 201 | 1 | 2010 | 1 | 11 | 23 | 3900000000 | | | | 58080 | 58080 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 1110105000 | 60200 | | | 376000 | 376000 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 2110300000 | 60200 | | | -545000 | -545000 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 1220221600 | | | | 452250 | 452250 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 2130323000 | | | | -165000 | -165000 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 2130322000 | | | | -118250 | -118250 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 3100505000 | | | | -937750 | -937750 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 3200652500 | | | | 819500 | 819500 |
| 201 | 1 | 2010 | 1 | 11 | 26 | 3900000000 | | | | 118250 | 118250 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 1110105000 | 60200 | | | 777000 | 777000 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 2110308000 | 60200 | 43 | | -255000 | -255000 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 2130321500 | | | | 180000 | 180000 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 2130322000 | | | | -77000 | -77000 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 2310407001 | | 1 | | -625000 | -625000 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 3100505000 | | | | -2502500 | -2502500 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 3200652500 | | | | 2425500 | 2425500 |
| 201 | 1 | 2010 | 1 | 11 | 37 | 3900000000 | | | | 77000 | 77000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1110105000 | 60200 | | | 2600000 | 2600000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1140161000 | 60200 | | 23 | 430000 | 430000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1140161000 | 60200 | | 26 | 505556 | 505556 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1140160000 | 60200 | 37 | | 255000 | 255000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1160163000 | 60200 | 99999 | 48 | 49428895 | 49428895 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1160163000 | 60200 | 99999 | 49 | 188260175 | 188260175 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 2310405500 | | | | -237689070 | -237689070 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 2110300000 | 60200 | | | -1000 | -1000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 2110300500 | 60200 | | | -3999000 | -3999000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 1220221600 | | | | 1571112 | 1571112 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 2130321500 | | | | -805556 | -805556 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 2130322000 | | | | -556112 | -556112 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 3100505000 | | | | -836000 | -836000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 3200652500 | | | | 781000 | 781000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 3300715700 | | 99999 | 32 | -440000 | -440000 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 3300715700 | | 99999 | 26 | -61112 | -61112 |
| 201 | 1 | 2010 | 1 | 11 | 43 | 3900000000 | | | | 556112 | 556112 |
+---------+------------+------+--------+------+---------+------------+-------+---------+----------+------------+------------+
I need to take all rows with Mvt = 60200 and multiply every GC and LC record in that row by 1.1 and add a new row containing the changes back into the same table with FY set to 2011.
How can I do all this in 1 statement?
Is it even possible to do all this in 1 statement (I know very little about SQL)?
Can this be done in standard SQL as the database will be ported to another Database Server?
I don't know which server it will be.
In standard SQL (there may be better ways in vendor-specific implementations but I tend to prefer standard stuff where possible):
insert into mytable (
Version, Yr_Varient, Period, CoA, Company, Item, Mvt, Ptnr_Co, Investee,
FY, GC, LC
) select
Version, Yr_Varient, Period, CoA, Company, Item, Mvt, Ptnr_Co, Investee,
2011, GC*1.1, LC*1.1
from mytable
where Mvt = 60200
-- and FY = 2010
You may also want to limit your select statement a little more depending on the results of your testing, such as uncommenting the and FY = 2010 line above to stop copying all your 2009 and 2008 data as well, if any. I asume you only wanted to carry forward the previous year's stuff with a 10% increase on GC and LC.
The way this works is to run the select which gives modified data for FY, GC and LC as per your request, and pump all those rows back into the insert.
insert into mytable (
Version,Yr_Varient,FY,Period,CoA,Company,Item,Mvt,Ptnr_Co,Investee,GC,LC)
SELECT Version ,Yr_Varient,"2011" as FY, Period, CoA, Company , Item , Mvt ,Ptnr_Co , Investee , GC*1.1 as GC, LC*1.1 as LC FROM <table Name>
WHERE Mvt = 60200
INSERT INTO _table_
(Version,
Yr_Varient,
FY,
Period,
CoA,
Company,
Item,
Mvt,
Ptnr_Co,
Investee,
GC,
LC)
SELECT
Version,
Yr_Varient,
2011,
Period,
CoA,
Company,
Item,
Mvt,
Ptnr_Co,
Investee,
GC * 1.1,
LC * 1.1
FROM
_table_
WHERE
Mvt = 60200
AND FY <> 2011
This statement should work in any SQL-Database.
Edit: Too slow