I have two tables having parent-child relationship
Table1
| Account_no | Main_account_no | bla bla
+------------+-----------------+----------
| 234 | 111 |
| 235 | 111 |
| 222 | 112 |
| 220 | 112 |
The second:
Table2
| Account_no | Balance | bla bla
+------------+-----------------+----------
| 234 | 10 |
| 235 | 15 |
| 222 | 55 |
| 220 | 45 |
What I need is to calculate the sum of balance of child accounts for each parent account.
The expected result is
| Main_account_no | Balance |
+-----------------+---------+
| 111 | 35 |
| 112 | 100 |
I am trying to use
SELECT MAIN_ACCOUNT_NO, SUM((SELECT BALANCE FROM TABLE2 WHERE ACCOUNT_NO = A.ACCOUNT_NO)) OVER (PARTITION BY MAIN_ACCOUNT_NO)
FROM TABLE1 A
GROUP BY MAIN_ACCOUNT_NO
But I get the ORA-00979: not a GROUP BY expression
Where did I do wrong?
Since this apparently isn't homework... :-)
First let's get the main_account_nos alongside the balances:
select
Table1.Main_account_no,
Table1.Account_no,
Table2.Balance
from
Table1
join Table2 on Table1.Account_no = Table2.Account_no
Gives
| Main_account_no | Account_no | Balance |
+-----------------+------------+-----------------+
| 111 | 234 | 10 |
| 111 | 235 | 15 |
| 112 | 222 | 55 |
| 112 | 220 | 45 |
Now we can easily group as required:
select
Table1.Main_account_no,
sum(Table2.Balance) as total
from
Table1
join Table2 on Table1.Account_no = Table2.Account_no
group by
Table1.Main_account_no
Related
Table1 has employee ids and codes where each employee has both super-set code and subset codes.
+-------------+------+
| Employee ID | Code |
+-------------+------+
| 111 | 18 |
| 111 | 19 |
| 111 | 20 |
| 111 | 21 |
| 222 | 40 |
| 222 | 41 |
| 222 | 42 |
+-------------+------+
Table2 has super-set code and subset code.
+---------------+-------------+
| Superset code | Subset code |
+---------------+-------------+
| 18 | 19 |
| 18 | 20 |
| 18 | 21 |
| 40 | 41 |
| 40 | 42 |
+---------------+-------------+
I want output with employee id and super-set code alone.
Expected result table:
+-------------+------+
| Employee ID | Code |
+-------------+------+
| 111 | 18 |
| 222 | 40 |
+-------------+------+
How can I derive this output using sql query?
I think you want exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.supersetcode = t1.code);
For performance, you want an index on table2(supersetcode).
I am trying to get a full table with an additional column with a count distinct grouped by only a set of fields, not the full table.
Basically, I have this table:
| mandt | ktopl | yhkonto | yhhykto | yhbwkz |
|-------|-------|------------|---------|--------|
| 111 | SAG | 0034600000 | 346 | 1 |
| 111 | SAG | 0034600000 | 346 | 21 |
| 111 | SAG | 0034600000 | 346 | 82 |
| 111 | SAG | 0034600000 | 346 | 87 |
| 111 | SAG | 0039410000 | 39410 | 1 |
| 111 | SAG | 0039410000 | 39410 | 21 |
| 111 | SAG | 0039410000 | 39410 | 82 |
| 111 | SAG | 0039410000 | 39410 | 87 |
| 111 | SAG | 0039630000 | 39630 | 1 |
| 111 | SAG | 0039630000 | 39630 | 21 |
and I want to get this result, with an additional column, where I get the count of distinct values of yhhykto grouping by mandt, ktopl and yhkonto:
| mandt | ktopl | yhkonto | yhhykto | yhbwkz | cnt_yhhykto |
|-------|-------|------------|---------|--------|-------------|
| 111 | SAG | 0034600000 | 346 | 1 | 1 |
| 111 | SAG | 0034600000 | 346 | 21 | 1 |
| 111 | SAG | 0034600000 | 346 | 82 | 1 |
| 111 | SAG | 0034600000 | 346 | 87 | 1 |
| 111 | SAG | 0039410000 | 39410 | 1 | 1 |
| 111 | SAG | 0039410000 | 39410 | 21 | 1 |
| 111 | SAG | 0039410000 | 39410 | 82 | 1 |
| 111 | SAG | 0039410000 | 39410 | 87 | 1 |
| 111 | SAG | 0039630000 | 39630 | 1 | 1 |
| 111 | SAG | 0039630000 | 39630 | 21 | 1 |
I have a working query:
select distinct yh010.mandt,
yh010.ktopl,
yh010.yhkonto,
yh010.yhhykto,
yh010.yhbwkz,
yh010_x.cnt_yhhykto
from yh010
inner join (
select distinct yh010.mandt,
yh010.ktopl,
yh010.yhkonto,
count(distinct yh010.yhhykto) as cnt_yhhykto
from yh010
group by yh010.mandt, yh010.ktopl, yh010.yhkonto
) yh010_x
on yh010_x.mandt = yh010.mandt
and yh010_x.ktopl = yh010.ktopl
and yh010_x.yhkonto = yh010.yhkonto
;
But this inner join with itself doesn't seem the best solution. Or is it?
I was thinking more like in terms of:
select yh010.mandt,
yh010.ktopl,
yh010.yhkonto,
yh010.yhhykto,
yh010.yhbwkz
count( distinct yh010.yhhykto
) over ( group by yh010.mandt, yh010.ktopl, yh010.yhkonto
) as cnt_dist
from yh010
;
But Incorrect syntax near the keyword 'distinct'.
Should I keep that working query or is there any better option?
The fiddle can be found here
Thank you!
Based on this description:
I want to get this result, getting the count of distinct values of
yhhykto grouping by mandt, ktopl and yhkonto
You want this query:
select y.mandt, y.ktopl, y.yhkonto,
count(distinct y.yhhykto)
from yh010 y
group by y.mandt, y.ktopl, y.yhkonto;
Your actual results and resulting query don't match the description, leaving me a bit confused.
Antonio,
Could you please test following SELECT statement with CTE expression
with cte as (
select
distinct mandt, ktopl, yhkonto, yhhykto
from TBL1
)
select
TBL1.*, (
select count(cte.yhhykto)
from cte
where
TBL1.mandt = cte.mandt and
TBL1.ktopl = cte.ktopl and
TBL1.yhkonto = cte.yhkonto
) as cnt
from TBL1
With tables table1 and table2need select the rows of table1 for those locationIds and hours where tier in table2 is high
table1
+------------+------+---------+----------+
| locationId | hour | metric1 | metric2 |
+------------+------+---------+----------+
| 1111 | 10 | 200 | 40 |
| 1111 | 9 | 300 | -20 |
| 1111 | 11 | 1800 | 300 |
| 1122 | 9 | 600 | 800 |
| 1122 | 11 | 2300 | -10 |
| 1133 | 8 | 10000 | 30 |
+------------+------+---------+----------+
table2
+------------+------+-------+---------+
| locationId | hour | value | tier |
+------------+------+-------+---------+
| 1111 | 10 | 1300 | high |
| 1111 | 9 | 900 | medium |
| 1111 | 11 | 200 | low |
| 1122 | 9 | 100 | low |
| 1122 | 11 | 2300 | high |
| 1133 | 8 | 1400 | high |
+------------+------+-------+---------+
If it was one column - say locationId I could have done something like
select * from table1
where locationId in (select locationId from table2 where tier='high');
How do I do this when the locationId, hour pair need to be compared?
output
+------------+------+---------+----------+
| locationId | hour | metric1 | metric2 |
+------------+------+---------+----------+
| 1111 | 10 | 200 | 40 |
| 1122 | 11 | 2300 | -10 |
| 1133 | 8 | 10000 | 30 |
+------------+------+---------+----------+
I think a simple join should handle this:
SELECT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.locationId = t2.locationId AND
t1.hour = t2.hour
WHERE t2.tier = 'high'
Output:
Demo here:
Rextester
The INNER JOIN keyword selects all rows from both tables as long as there is a match between the columns in both tables.
select * from table1 t1
inner join table2 t2 on t1.locationId =t2.locationId
where t2.tier='high'
Use EXISTS method to get your result :
SELECT *
FROM table1 TBL1 WHERE EXISTS
(
SELECT 1 FROM table2 TBL2 WHERE TBL1.locationId = TBL2.locationId AND
TBL1.hour = TBL2.hour AND TBL2.tier = 'high'
)
I have 2 tables
Table A:
+------------+----------+
| Entry From | Entry To |
+------------+----------+
| 100 | 103 |
| 104 | 105 |
| 106 | 109 |
+------------+----------+
Table B:
+-------+-------+
| Entry | Value |
+-------+-------+
| 100 | 10 |
| 101 | 3 |
| 102 | 7 |
| 103 | 2 |
| 104 | 9 |
| 105 | 17 |
| 106 | 3 |
| 107 | 3 |
| 108 | 6 |
| 109 | 5 |
+-------+-------+
Desired result:
+------------+----------+-------------+
| Entry From | Entry To | Total Value |
+------------+----------+-------------+
| 100 | 103 | 22 |
| 104 | 105 | 26 |
| 106 | 109 | 17 |
+------------+----------+-------------+
Any solutions/advice is welcome.
Thanks to any help in advance!
Please try:
Select
a.EntryFrom, a.EntryTo, sum(Value) TotalValue
From TableA a INNER JOIN TableB b ON b.Entry between a.EntryFrom and a.EntryTo
Group by a.EntryFrom, a.EntryTo
What you're looking for is a subquery maybe.
SELECT
A.Entry_From, A.Entry_To,
(SELECT SUM(B.Value) FROM B
WHERE B.Entry BETWEEN A.Entry_From AND A.Entry_To) AS Total_Value
FROM A
It also depends on what version of SQL so YMMV :)
Here is a working fiddle: http://www.sqlfiddle.com/#!2/afbac/2 using this query:
select a.idxFrom, a.idxTo, sum(b.value) as total
from a inner join b on b.idx >= a.idxFrom and b.idx <= a.idxTo
group by a.idxFrom, a.idxTo
I'm creating inventory report mainly to show current qty, sum of qty that was reserved from customers and Total Qty that available .
As I used LEFT JOIN and RIGHT JOIN but it couldn't work, so I'm thinking of UNION function but I could't make it work. Could you please help me. Thank you very much.
tbl_inventory
inv_id | pd_id | inv_qty_act | inv_date | inv_note
1 | 001 | 120 | 20-Sep-12|
2 | 003 | 387 | 1-Oct-12 |
tbl_reserve
res_id | cust_id | res_date | res_duedate | pd_id | res_qty | if_sent | res_note
3 | 10 | 01-Oct-12| 17-Oct-12 | 001 | 135 | |
4 | 9 | 01-Oct-12| 24-Oct-12 | 001 | 253 | |
5 | 22 | 01-Oct-12| 17-Oct-12 | 001 | 132 | |
6 | 2 | 01-Oct-12| 24-Oct-12 | 002 | 446 | |
tbl_product
pd_id | pd_name
001 | des1
002 | des2
003 | des3
tbl_pdtn_startup
pdtn_st_id | pd_id | pdtn_qty_est
2 | 002 | 200
3 | 003 | 100
Output that I want :
pd_id| pd_name| inv_qty_act|pdtn_qty_est| Sum(res_qty)| Total[(inv_qty_est) - Sum(res_qty)]
001 | des1 | 120 | 0 | 520 | -400 -->(120-520)
002 | des2 | 0 | 200 | 446 | -446 -->(0-446)
003 | des3 | 387 | 100 | 0 | 387
what about this?
SELECT
tbl_product.pd_id,
tbl_product.pd_name,
( SELECT Sum(inv_qty_act) FROM tbl_inventory AS t1
WHERE t1.pd_id=tbl_product.pd_id) AS SumOfinv_qty_act,
( SELECT Sum(pdtn_qty_est) FROM tbl_pdtn_startup AS t2
WHERE t2.pd_id =tbl_product.pd_id) AS SumOfpdtn_qty_est,
( SELECT Sum(res_qty) FROM tbl_reserve AS t3
WHERE t3.pd_id=tbl_product.pd_id) AS SumOfres_qty,
IIF(ISNULL([SumOfinv_qty_act]),0,[SumOfinv_qty_act])-
IIF(ISNULL([SumOfres_qty]),0,[SumOfres_qty]) AS Total
FROM
tbl_product;