So I have this table with an unique identifier and its group; I want to get totals of another table based on its Group
Table 1
UNIQUE_ID ! Group
1 West
2 West
3 West
4 West
5 West
6 East
7 East
Then I have this second table from with which I join
Table 2
UNIQUE_ID ! NET PROFIT ! ASSETS ! EQUITY ! YEAR
1 100 100 100 2016
1 100 100 100 2015
2 100 100 100 2016
2 100 100 100 2015
3 100 100 100 2016
3 100 100 100 2015
***4 10 10 10 2015***
5 100 100 100 2016
5 100 100 100 2015
***6 10 10 10 2014***
7 100 100 100 2016
7 100 100 100 2015
7 100 100 100 2014
I link the previous tables and I group by Group which then gives me the totals for NEt profit, assets and equity, the problem is that it sums all the years available in table 2 Or I do a where year is 2016 and I only get the totals from 2016 not including the rows which id have the latest year of 2015 or 2014
I need it to group by Group and sum only the last available year for each unique ID, so that I would get the following table
Query would give me this table
Group ! NET PROFIT ! ASSETS ! EQUITY
East 410 410 410
West 110 110 110
Can anyone help me? I've looked everywhere and tried a number of combinations but without success
Consider a join of an aggregate derived table to the join of other two tables where essentially the last INNER JOIN acts as a WHERE clause to filter select years for each unique_id.
SELECT t1.`GROUP`, SUM(t2.NET_PROFIT) AS SUM_NET_PROFIT,
SUM(t2.ASSETS) AS SUM_ASSETS,
SUM(t2.EQUITY) AS SUM_EQUITY
FROM (`table2` t2
INNER JOIN `table1` t1
ON t1.UNIQUE_ID = t2.UNIQUE_ID)
INNER JOIN
(SELECT t2.UNIQUE_ID, MAX(t2.`YEAR`) AS MAX_YEAR
FROM `table2` t2
GROUP BY t2.UNIQUE_ID) g
ON t2.`UNIQUE_ID` = g.`UNIQUE_ID` AND t2.`YEAR` = g.`MAX_YEAR`
GROUP BY t1.`GROUP`;
Do note the parentheses used to wrap first join pairing of tables, required in MS Access.
Is this what you want?
SELECT Group_,
SUM(NET_PROFIT) AS NET_PROFIT_YR,
SUM(ASSETS) AS ASSETS_YR,
SUM(EQUITY) As EQUITY_YR
FROM Table1 AS T1
INNER
JOIN (SELECT T2_RAW.*
FROM ( SELECT Unique_ID,
MAX(year) AS m_year
FROM Table2 AS T2
GROUP
BY Unique_ID
) AS MYR
INNER
JOIN Table2 AS T2_RAW
ON MYR.unique_id = T2_RAW.unique_id
AND MYR.m_year = T2_RAW.year
) AS TMP
ON T1.unique_id = TMP.unique_id
GROUP
BY group_;
I. The complete SQL statement:
SELECT
ta.group,
SUM(IFNULL(tb.net_profit, 0)) as sumNetProfit,
SUM(IFNULL(tb.assets, 0)) as sumAssets,
SUM(IFNULL(tb.equity, 0)) as sumEquity
FROM table_a AS ta
LEFT JOIN (
SELECT
unique_id,
max(year) as maxYear
FROM table_b
GROUP BY unique_id
) AS tbMaxYears ON tbMaxYears.unique_id = ta.unique_id
LEFT JOIN table_b AS tb ON
tb.unique_id = ta.unique_id
AND tb.year = tbMaxYears.maxYear
GROUP BY ta.group;
II. Description:
The inner query:
SELECT
unique_id,
max(year) as maxYear
FROM table_b
GROUP BY unique_id
Selects the unique_ids from table_b and, for each unique_id, the corresponding latest year, e.g. the maximal year;
Groups the fetched records by the unique_id;
Is used in a LEFT JOIN statement under the alias maxYears and its results are filtered by the unique_ids fetched from the table_a.
The inner query results looks like following:
unique_id maxYear
-------------------
1 2016
2 2016
3 2016
4 2015
5 2016
6 2014
7 2016
The outer query:
SELECT
ta.group,
SUM(IFNULL(tb.net_profit, 0)) as sumNetProfit,
SUM(IFNULL(tb.assets, 0)) as sumAssets,
SUM(IFNULL(tb.equity, 0)) as sumEquity
FROM table_a AS ta
LEFT JOIN (
<THE-INNER-QUERY-RESULTS>
) AS tbMaxYears ON tbMaxYears.unique_id = ta.unique_id
LEFT JOIN table_b AS tb ON
tb.unique_id = ta.unique_id
AND tb.year = tbMaxYears.maxYear
GROUP BY ta.group;
Reads all table_a records;
Attaches the maxYears details (fetched through the inner query);
Attaches the table_b details;
Groups the records by the group column;
Calculates the corresponding sums (including NULL values validation).
The results of the outer query (e.g. the final results):
group sumNetProfit sumAssets sumEquity
---------------------------------------------
East 110 110 110
West 410 410 410
The second LEFT JOIN in the outer query:
LEFT JOIN table_b AS tb ON
tb.unique_id = ta.unique_id
AND tb.year = tbMaxYears.maxYear
Attaches (joins) the table_b details to the records fetched from table_a;
Only the table_b records are attached, which have the same unique_id as the corresponding unique_id value from table_a AND (!) the same year as the corresponding maxYear value from maxYears table.
III. Used table structure:
I used a MySQL database with the following CREATE TABLE syntax:
CREATE TABLE `table_a` (
`unique_id` int(11) DEFAULT NULL,
`group` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `table_b` (
`unique_id` int(11) DEFAULT NULL,
`net_profit` int(11) DEFAULT NULL,
`assets` int(11) DEFAULT NULL,
`equity` int(11) DEFAULT NULL,
`year` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I used the same data as you.
Good luck!
Related
In sql help i have 3 tables, table one is asset table which is as follow
id
asset_code
asset_name
asset_group
asset_quantity
1
A001
demo asset
4
5
2
A002
demo asset 2
6
3
and another table is asset_allocation
id
asset_id
allocated_quantity
allocated_location
1
1
2
IT office
2
1
1
main hall
the last table is asset_liquidated which will present assets that are no longer going to be used
id
asset_id
liquidated_quantity
1
1
2
2
1
1
lets say i have 5 computers and i have allocated 3 computers and 1 is no longer going to be used so i should be remaining with 1 computer so now how do i make sql auto generate this math for me
You need to use aggregation and the join your tables -
SELECT id, asset_code, asset_name, asset_group, asset_quantity,
asset_quantity - COALESCE(AA.allocated_quantity, 0) - COALESCE(AL.liquidated_quantity, 0) available_quantity
FROM asset A
LEFT JOIN (SELECT asset_id, SUM(allocated_quantity) allocated_quantity
FROM asset_allocation
GROUP BY asset_id) AA ON A.id = AA.asset_id
LEFT JOIN (SELECT asset_id, SUM(liquidated_quantity) liquidated_quantity
FROM asset_liquidated
GROUP BY asset_id) AL ON A.id = AL.asset_id
This query will give you -1 as available_quantity for asset_id 1 as you have only 5 available, 3 of them are allotted and 3 are liquidated as per your sample data.
Please see if this helps
SELECT
asset_quantity AS Total_Assets
,ISNULL(allocated_quantity, 0) allocated_quantity
,ISNULL(liquidated_quantity, 0) liquidated_quantity
FROM asset
LEFT OUTER JOIN (
SELECT
asset_id, SUM(allocated_quantity) AS allocated_quantity
FROM asset_allocation
GROUP BY asset_id
) asset_allocation2
ON asset_allocation2.asset_id = asset.id
LEFT OUTER JOIN (
SELECT
asset_id, SUM(liquidated_quantity) AS liquidated_quantity
FROM asset_liquidated
GROUP BY asset_id
) asset_liquidated 2
ON asset_liquidated 2.asset_id = asset.id
I have a table as
Person| Count
A | 10
B | 20
C | 30
I use code as below to get above table:
select new_table.person, count(new_table.person)
from (person_table_1
inner join person_table_2
on person_table_1.user_name = person_table_2.user_all_name) new_table
group by new_table.person
However, I wish to have the percentage for each row based on overall sum in count.
Expected:
Person| Count | Percentage
A | 10 | 0.167
B | 20 | 0.333
C | 30 | 0.500
I wish it to be in 3 decimal places. Can anyome please help me. thank you.
Just do an inner query in SELECT clause
select p1.person, count(p1.person), count(p1.person) / (SELECT COUNT(p2.person) FROM person_table p2)
from person_table p1
group by p1.person
Edit: if you want only up to 3 decimal:
select
p1.person,
count(p1.person),
ROUND(count(p1.person) / (SELECT COUNT(p2.person) FROM person_table p2), 3)
from person_table p1
group by p1.person
Edit 2: OP edited his/her table
select
new_table.person,
count(new_table.person),
ROUND(
count(new_table.person) /
SELECT COUNT(new_table_COUNTER.person) FROM (
person_table_1
inner join person_table_2
on person_table_1.user_name = person_table_2.user_all_name
) new_table_COUNTER )
from
(
person_table_1
inner join person_table_2
on person_table_1.user_name = person_table_2.user_all_name
) new_table
group by new_table.person
Try below query:
declare #tbl table ([person] varchar(5));
insert into #tbl values
('a'),('a'),('a'),('b'),('b'),('c');
-- here we tabke max(rowsCnt), but we wwant any value, because every value is the same in that column
select person, count(*) * 1.0 / max(rowsCnt) [percentage] from (
select person,
count(*) over (partition by (select null)) rowsCnt
from #tbl
) a group by person
I have a Table that is joined from other tables. I want to update a null value in this Table by a specific number series. Below is the illustration:
The code for the Table which is called List_Codes
SELECT mlk.MLK_CODE
FROM zpt
LEFT OUTER JOIN mes ON mes.ZPT_ID = zpt.ZPT_ID
LEFT OUTER JOIN zmlk ON zpt.ZPT_ID = zmlk.ZPT_ID
LEFT OUTER JOIN mlk ON zmlk.MLK_ID = mlk.MLK_ID
WHERE zpt.zpt_id IS NOT NULL
and zpt.zpt_meteringcode = '123456'
ORDER BY mes.MES_STATUS DESC
Now I want to update this specific row's mlk.MLK_CODE from null to '789'. I have located this row based on the zpt.zpt_meteringcode. Any suggestions plz?
The tables look like this, and the List_Code Table is the result of the above code
Mlk Table
Mlk_id Mlk_code
1 123
2 456
Zpt Table
Zpt_id Zpt_meteringcode
10 123456
20 987654
30 654321
40 147852
Zmlk Table
Zpt_id Mlk_id
20 1
30 2
List_Code Table
Zpt_id Zpt_meteringcode Mlk_id Mlk_code
10 123456
20 987654 1 123
30 654321 2 456
40 147852
I think you need two inserts and one update statements like this.
INSERT INTO mlk (mlk_code)
VALUES ( '789' ); -- Primary key is generated
.....
INSERT INTO zmlk (zpt_id,
mlk_id)
SELECT (SELECT zpt_id
FROM zpt
WHERE zpt_meteringcode = '123456'),
(SELECT mlk_id
FROM mlk
WHERE mlk_code = '789')
FROM dual;
....
UPDATE list_code
SET ( mlk_id, mlk_code ) = (SELECT mlk_id,
mlk_code
FROM mlk
WHERE mlk_code = '789')
WHERE zpt_meteringcode = '123456';
There's a payment table with these fields:
Dossier_id
Year
Amount
Payed
Retarded
( all fields are numeral )
Imagine the table with these entries:
Dossier_id || Year || Amount || Payed || Retarded
==================================================================
1000 2010 500 100 400
2000 2007 700 500 200
1000 2011 1200 700 500
2000 2009 900 800 100
==================================================================
Total || 3300 2100 600
==================================================================
How can i write a query to calculate (only) the end section of that table (Total) to achieve the correct Retarded rate as total liability? ( i played with inner join but i couldn't figure it well)
This should do it:
SELECT SUM(a.amount), sum(a.payed), b.retarded
FROM table a INNER JOIN (SELECT SUM(retarded) AS retarded
FROM table b INNER JOIN (SELECT dossier_id, MAX(year) FROM table) c ON b.dossier_id = c.dossier_id AND b.year = c.year) b ON 1 = 1
EDIT (stupid access - join not supported issue):
SELECT SUM(a.amount), sum(a.payed), b.retarded
FROM table a INNER JOIN (SELECT SUM(retarded) AS retarded
FROM table b INNER JOIN (SELECT dossier_id, MAX(year) FROM table) c ON (b.dossier_id = c.dossier_id AND b.year = c.year)) b ON (1 = 1)
Its this simple query:
SELECT SUM(AMOUNT), SUM(PAYED), SUM(RETARDED) FROM TABLE;
I have two tables tabeleA and tableB..
In table A, I have column(Name)
In table B, I have column(Amount)
Table A:
cat_id cat_name
1 Man
2 Women
3 General
Table B:
cat_id cat_price
1 12
1 18
1 34
1 23
2 21
3 31
1 21
3 56
Now in these two tables I have name and price which are linked by cat_id..
Now I want to display Name and price for that particular name and the price should be the total for particular categories......
Something like this:
TableNew:
cat_name cat_price
Man 104
Woman 21
General 87
please help..
thanks...
SELECT
tA.cat_name, SUM(tB.cat_price) AS price
FROM TableA tA
INNER JOIN TableB tB
ON tA.cat_id=tB.cat_id
GROUP BY tA.cat_id
select a.cat_name,
sum(b.cat_price) price
from tablea a
inner join tableb b
on a.cat_id = b.cat_id
group by a.cat_name
INNER JOIN.
GROUP BY Sql Server version in absence of Wiki Sql article.
select T1.cat_name, T2.total
from TableA T1
NATURAL JOIN (SELECT cat_id, sum(cat_price) as total
FROM TableB GROUP BY cat_id) T2
You can use an INNER JOIN for this:
SELECT
table_a.cat_name,
SUM(table_b.cat_price) AS price
FROM
table_a
INNER JOIN
table_b
ON
table_b.cat_id = table_a.cat_id
GROUP BY
table_a.cat_name;
Hope this helps.