Combine 2 SQL queries - sql

I'm stuck on a SQL issue, I'm almost sure it's all easy but I can't find a proper answer. Below here is the example. I want to combine those 2 queries :
SELECT
num_rata, SUM(val_imp*0.01) AS amount
FROM table1
WHERE
col1 <> 0
AND num_contract = 88
GROUP BY num_rata
That returns something like :
1 215.00
2 220.00
3 210.00
4 115.00
5 315.00
And :
SELECT
num_rata, SUM(val_ban*0.01) AS amount
FROM table2
WHERE
num_contract = 2988
GROUP BY num_rata;
Example result set :
1 15.00
2 615.00
3 275.00
4 285.00
5 285.00
6 275.00
7 260.00
8 215.00
9 215.00
As a final result I would like something like this :
1 215.00 15.00
2 220.00 615.00
3 210.00 275.00
4 115.00 285.00
5 315.00 285.00
6 275.00
7 260.00
8 215.00
9 215.00
Thank you for any hint.
fabien.

You could use either a union or an outer join - I would prefer a union, like this:
SELECT num_rata, sum(val_imp)*0.01 imp_amount, sum(val_ban)*0.01 ban_amount
from (SELECT num_rata, val_imp, 0 val_ban
FROM table1
WHERE col1 <> 0 AND num_contract = 88
UNION ALL
SELECT num_rata, 0 val_imp, val_ban
FROM table2
WHERE num_contract = 2988) v
GROUP BY num_rata;

I think this is what you want:
select
t1.num_rata,
SUM(t1.val_imp*0.01) AS amount1,
SUM(t2.val_ban*0.01) AS amount2
from
table1 t1 right outer join table2 t2 on t1.num_rata=t2.num_rata
where
t1.col1<>0 and
t1.num_contract = 88 and
t2.num_contract = 2988
GROUP BY t1.num_rata

Can you try what will this do:
SELECT num_rata, (
coalesce(
(SELECT SUM(val_imp*0.01) FROM table1 t1 WHERE t1.num_rata = foo.num_rata)
,0)
) as col1, (
coalesce(
(SELECT SUM(val_ban*0.01) FROM table2 t2 WHERE t2.num_rata = foo.num_rata)
,0)
) as col2 FROM
(
(SELECT num_rata FROM table1 WHERE col1 <> 0 AND num_contract = 88)
UNION ALL
(SELECT num_rata FROM table2 WHERE num_contract = 2988)
) as foo;
I might have syntax error (I am writing this from a university lecture), but this (or similar) should do the trick.

Related

Conditional sum in SQL (SAS) (SUMIFS equivalent)

Let say I am working under SAS EG and I have 2 tables:
Table1:
Id Item
1 A
1 B
1 C
2 B
2 D
3 C
3 E
3 F
Table2:
Id Item Amount
1 A 99
2 C 100
1 B 100
2 A 90
1 A 93
3 B 92
1 E 93
2 B 99
1 A 93
Now I would like to take the sum conditional for my table1 from table2 (when the ID and the Item match).
Id Item Want
1 A 285
1 B 100
1 C 0
2 B 99
2 D 0
3 C 0
3 E 0
3 F 0
So what am I supposed to do in SQL?
Thanks in advance.
Use a correlated subquery to SUM:
select t1.Id, t1.Item,
(select sum(t2.amount) from table2 t2 where t2.id = t1.id and t2.item = t1.item)
from table1 t1
This looks like aggregation to me, with a left join:
select t1.id, t1.item,
coalesce(sum(t2.amount), 0) as want
from table1 t1 left join
table2 t2
on t1.id = t2.id and t2.item = t2.item
group by t1.id, t1.item;

How to join and count with multiple condition in oracle

i have 2 tables :
table1(id, name)
1233 AAA
3424 BBB
4345 CCC
4342 DDD
1243 RRR
3453 GGG
table2(id,date,status)
1233 01/07/19 1
3424 01/07/19 1
4342 01/07/19 2
1243 01/07/19 1
4342 01/07/19 1
4345 02/07/19 2
1243 02/07/19 1
1233 02/07/19 1
4345 03/07/19 1
4342 03/07/19 2
1233 03/07/19 1
4342 04/07/19 2
4345 04/07/19 2
4342 04/07/19 1
1243 04/07/19 2
15 ROW
i have tried this code
SELECT rn.id, name, NVL(cnt, 0) jum
FROM table1 rn
LEFT JOIN (SELECT id, COUNT(id) AS cnt
FROM VIEW_AKTIFITAS
WHERE extract(year from date)=2019
AND extract(month from date)=7
GROUP BY id,extract(month from date) n ON n.id= rn.id
i want to get this result
how to count the status entry in table 2
RESULT
ID COUNT_STATUS_1 COUNT_STATUS_2 TOTAL_COUNT
1233 2 0 2
3424 2 0 2
4345 1 2 3
4342 2 3 5
1243 2 1 3
3453 0 0 0
please help me to solve this problem.. thanks
Left join table2 to table1 and then use conditional aggregation to get the different counts for the two status.
SELECT t1.id,
count(CASE
WHEN t2.status = 1 THEN
1
END) count_status_1,
count(CASE
WHEN t2.status = 2 THEN
1
END) count_status_2,
count(t2.status) total_count
FROM table1 t1
LEFT JOIN table2 t2
ON t2.id = t1.id;
In Oracle 11.1 and higher, you can use the PIVOT operator to do the aggregation. Something like this:
select id, name, count_status_1, count_status_2,
count_status_1 + count_status_2 as total_count
from (select t1.id, t1.name, t2.status from table1 t1 left join table2 t2
on t1.id = t2.id)
pivot (count(*) for status in (1 as count_status_1, 2 as count_status_2))
order by id -- if needed
;
Based on your sample code, you seem to want:
SELECT rn.id, rn.name, NVL(cnt, 0) jum,
SUM(CASE WHEN a.status = 1 THEN 1 ELSE 0 END) as status_1,
SUM(CASE WHEN a.status = 1 THEN 1 ELSE 0 END) as status_2,
COUNT(a.status) as total
FROM table1 rn LEFT JOIN
VIEW_AKTIFITAS a
ON a.id = rn.id AND
a.date >= DATE '2019-07-01' AND
a.date < DATE '2019-08-01'
GROUP BY rn.id, rn.name;
You do not need a subquery for the LEFT JOIN. The date comparisons are better done using direct date comparisons. Oracle allows you to use ISO-standard date formats with the DATE keyword.
this is my final code
SELECT t1.nip, t1.nama_pegawai,
count(CASE
WHEN t2.status = 1
and t2.tahun=2019
and t2.bulan=7
THEN
1
END) count_status_1,
count(CASE
WHEN t2.status = 2
and t2.tahun=2019
and t2.bulan=7
THEN
1
END) count_status_2,
count(CASE
WHEN t2.tahun=2019
and t2.bulan=7
THEN 1 END
) total_count
FROM VIEW_PEGAWAI t1
LEFT JOIN VIEW_AKTIFITAS t2
ON t2.nip = t1.nip
where t1.opd_id=14
and T1.JENIS_PEG<>3
group by t1.nip,t1.nama_pegawai

If value in both table then assign 1

Table1 CompanyID Location #-of-employees
5234 NY 10
5268 DC 2
5879 NY 8
6897 KS 100
8789 CA 1
9992 OH 201
9877 TX 15
Table2 CompanyID #-of-Shareholders
5234 5
5879 2
6897 4
8789 2
I have two table with the column CompanyID. In table2 you can find companies that have shareholders and in table1 you can find all the companies. So in table 1 I want to add a dummy variable that assign a 1 if the companyID is in table2(which means the company has shareholders) and a 0 if not.
Expected output:
Table1 CompanyID Location #-of-employees Dummy
5234 NY 10 1
5268 DC 2 0
5879 NY 8 1
6897 KS 100 1
8789 CA 1 1
9992 OH 201 0
9877 TX 15 0
I tried using this query but it doesn't give me the output I expect.
SELECT CASE WHEN companyID IN table2 THEN 1
ELSE 0
END AS dummy
FROM table1
You have to use the Subquery for this. the below code working fine.
SELECT CASE WHEN companyID in(select CompanyId from table2) THEN 1
ELSE 0
END AS dummy
FROM table1
You can use EXISTS
SELECT CASE
WHEN EXISTS(SELECT 1 FROM Table2 AS T2 WHERE T1.CompanyID = T2.CompanyID) THEN 1
ELSE 0
END AS Dummy
FROM Table1 AS T1;
If your DB's version is 2012+ then, use with left join as :
select t1.*, iif(#_of_Shareholders is null, 0, 1) as dummy
from table1 t1
left join table2 t2
on ( t1.CompanyID = t2.CompanyID );
else
select t1.*,
( case when #_of_Shareholders is null then 0 else 1 end )
as dummy
from table1 t1
left join table2 t2
on ( t1.CompanyID = t2.CompanyID );
or
select t1.*,
sign(coalesce(#_of_Shareholders,0))
as dummy
from table1 t1
left join table2 t2
on ( t1.CompanyID = t2.CompanyID );
Rextester Demo

Get next minimum, greater than or equal to a given value for each group

given the following Table1:
RefID intVal SomeVal
----------------------
1 10 val01
1 20 val02
1 30 val03
1 40 val04
1 50 val05
2 10 val06
2 20 val07
2 30 val08
2 40 val09
2 50 val10
3 12 val11
3 14 val12
4 10 val13
5 100 val14
5 150 val15
5 1000 val16
and Table2 containing some RefIDs and intVals like
RefID intVal
-------------
1 11
1 28
2 9
2 50
2 51
4 11
5 1
5 150
5 151
need an SQL Statement to get the next greater intValue for each RefID and NULL if not found in Table1
following is the expected result
RefID intVal nextGt SomeVal
------------------------------
1 11 20 val01
1 28 30 val03
2 9 10 val06
2 50 50 val10
2 51 NULL NULL
4 11 NULL NULL
5 1 100 val14
5 150 150 val15
5 151 1000 val16
help would be appreciated !
Derived table a retrieves minimal values from table1 given refid and intVal from table2; outer query retrieves someValue only.
select a.refid, a.intVal, a.nextGt, table1.SomeVal
from
(
select table2.refid, table2.intval, min (table1.intVal) nextGt
from table2
left join table1
on table2.refid = table1.refid
and table2.intVal <= table1.intVal
group by table2.refid, table2.intval
) a
-- table1 is joined again to retrieve SomeVal
left join table1
on a.refid = table1.refid
and a.nextGt = table1.intVal
Here is Sql Fiddle with live test.
You can solve this using the ROW_NUMBER() function:
SELECT
RefID,
intVal,
NextGt,
SomeVal,
FROM
(
SELECT
t2.RefID,
t2.intVal,
t1.intVal AS NextGt,
t1.SomeVal,
ROW_NUMBER() OVER (PARTITION BY t2.RefID, t2.intVal ORDER BY t1.intVal) AS rn
FROM
dbo.Table2 AS t2
LEFT JOIN dbo.Table1 AS t1 ON t1.RefID = t2.RefID AND t1.intVal >= t2.intVal
) s
WHERE
rn = 1
;
The derived table matches each Table2 row with all Table1 rows that have the same RefID and an intVal that is greater than or equal to Table2.intVal. Each subset of matches is ranked and the first row is returned by the main query.
The nested query uses an outer join, so that those Table2 rows that have no Table1 matches are still returned (with nulls substituted for the Table1 columns).
Alternatively you can use OUTER APPLY:
SELECT
t2.RefID,
t2.intVal,
t1.intVal AS NextGt,
t1.SomeVal
FROM
dbo.Table2 AS t2
OUTER APPLY
(
SELECT TOP (1)
t1.intVal
FROM
dbo.Table1 AS t1
WHERE
t1.RefID = t2.RefID
AND t1.intVal >= t2.intVal
ORDER BY
t1.intVal ASC
) AS t1
;
This method is arguably more straightforward: for each Table2 row, get all matches from Table1 based on the same set of conditions, sort the matches in the ascending order of Table1.intVal and take the topmost intVal.
This can be done with a join, group by, and a case statement, and a trick:
select t1.refid, t2.intval,
min(case when t1.intval > t2.intval then t1.intval end) as min_greater_than_ref,
substring(min(case when t1.intval > t2.intval
then right('00000000'+cast(t1.intval as varchar(255)), 8)+t1.SomeVal)
end)), 9, 1000)
from table1 t1 left join
table2 t2
on t1.refid = t2.refid
group by t1.refid, t2.intval
SO, the trick is to prepend the integer value to SomeValue, zero-padding the integer value (in this case to 8 characters). You get something like: "00000020val01". The minimum on this column is based on the minimum of the integer. The final step is to extract the value.
For this example, I used SQL Server syntax for the concatenation. In other databases you might use CONCAT() or ||.

Query results with no reverse

Ive got table:
UserA,
UserB,
numberOfConnections
I would like to write query which returns me only rows that has no reverse I mean or example :
for data :
1 2 10
1 3 10
1 5 10
1 6 10
2 6 10
2 5 10
5 1 10
5 2 10
3 1 10
it should return
1 2 10
1 3 10
1 5 10
1 6 10
2 6 10
2 5 10
rows:
5 1 10
5 2 10
3 1 10
arent valid because there are already corresponding
1 5 10
2 5 10
3 1 10
thanks for help
bye
This will do what you want
SELECT mt1.UserA, mt1.UserB, mt1.numberOfConnections
FROM MyTable mt1
LEFT OUTER JOIN MyTable mt2 ON mt1.UserA = mt2.UserB
AND mt1.UserB = mt2.UserA
WHERE mt2.UserA IS NULL
OR mt1.UserA < mt2.UserA
Why not add UserA < UserB in where clause. ?
Use Updated
A- Result No Reverse
Select UserA, UserB, numberOfConnections
From TName
Where ID Not IN(
SELECT t1.ID
FROM TName As t1 INNER JOIN TName As t2 ON (t1.UserA = t2.UserB) AND (t1.UserB = t2.UserA))
B- Result Reverse Only Repeted
Select UserA, UserB, numberOfConnections
From TName
Where ID IN(
SELECT t1.ID
FROM TName As t1 INNER JOIN TName As t2 ON (t1.UserA = t2.UserB) AND (t1.UserB = t2.UserA))
C- Result Reverse Only Not Repeted
Select UserA, UserB, numberOfConnections
From TName
Where ID IN(
SELECT t1.ID
FROM TName As t1 INNER JOIN TName As t2 ON (t1.UserA = t2.UserB) AND (t1.UserB = t2.UserA) and (t1.UserA<t1.UserB))
D- Result No Reverse and Not Repeted Reverse
A
Union
C
with t1 as (
select col1 ,col2,
row_number()
over(partition by case when col1>col2 then col1+col2 else col2+col1 end
order by case when col1>col2 then col1+col2 else col2+col1 end) as rownum
from table_1 )
select * from t1 where rownum =1
if your data type of col1 and col2 are not varchar, just cast them
you can replace the row_number by group by