Exclude subsets from a table which has superset values too - sql

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).

Related

How to return the maximum and minimum values for specific ID SQL

Given the following SQL tables: https://imgur.com/a/NI8VrC7. For each specific ID_t I need to return the MAX() and MIN() value of Cena_c(total price) column of a given ID_t.
| ID_t | Nazwa |
| ---- | ----- |
| 1 | T1 |
| 2 | T2 |
| 3 | T3 |
| 4 | T4 |
| 5 | T5 |
| 6 | T6 |
| 7 | T7 |
| ID | ID_t | Ilosc | Cena_j | Cena_c | ID_p |
| ---- | ---- | ----- | ------ | ------ | ---- |
| 100 | 1 | 1 | 10 | 10 | 1 |
| 101 | 2 | 3 | 20 | 60 | 2 |
| 102 | 4 | 5 | 10 | 50 | 7 |
| 103 | 2 | 2 | 20 | 40 | 5 |
| 104 | 5 | 1 | 30 | 30 | 5 |
| 105 | 7 | 6 | 80 | 480 | 1 |
| 106 | 6 | 7 | 15 | 105 | 2 |
| 107 | 6 | 5 | 15 | 75 | 1 |
| 108 | 3 | 3 | 25 | 75 | 7 |
| 109 | 7 | 1 | 80 | 80 | 5 |
| 110 | 4 | 1 | 10 | 10 | 2 |
| 111 | 2 | 9 | 20 | 180 | 2 |
Based on provided tables the correct result should look like this:
| ID_t | Cena_c_max | Cena_c_min |
| ----- | ---------- | ---------- |
| T1 | 10 | 10 |
| T2 | 180 | 60 |
| T3 | 75 | 75 |
| T4 | 50 | 10 |
| T5 | 30 | 30 |
| T6 | 105 | 75 |
| T7 | 480 | 80 |
Is this even possible?
I haven't found anything yet that I could use to implement my solution.
SELECT concat('T',ID_t), max(Cena_c) as Cena_c_max, min(Cena_c) as Cena_c_min
FROM table
GROUP BY ID_t
Better is to solve it with joins of tables, because it will be avoided in the future if the prefix T is changed to another letter.
Hardcoding should be avoided.
select b.nazva as "Nazva", max(a.cena.c) as "Cena_c_max", min(a.cena.c) as "Cena_c_min"
from table1 as a
left join table2 as b on (
a.id_t = b.id_t
)
group by id_t

Calculating sum of children's balance for each parent

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

Select rows with greatest value

I have a MS Access query called qryA380 that uses multiple INNER JOIN to join a couple of tables.
Running the query will show the results like this:
+----+-----------+----------+------------+
| ID | Aircraft | Route.ID | Passengers |
+----+-----------+----------+------------+
| 23 | A-380 | 1 | 556 |
| 2 | A-380 | 2 | 652 |
| 54 | A-380 | 2 | 489 |
| 16 | A-380 | 1 | 598 |
| 39 | A-380 | 1 | 627 |
| 45 | A-380 | 3 | 392 |
| 74 | A-380 | 3 | 726 |
+----+-----------+----------+------------+
My plan is to select the smallest Route.ID (in this case it's 1) and the final result should be:
+----+-----------+----------+------------+
| ID | Aircraft | MinRoute | Passengers |
+----+-----------+----------+------------+
| 23 | A-380 | 1 | 556 |
| 16 | A-380 | 1 | 598 |
| 39 | A-380 | 1 | 627 |
+----+-----------+----------+------------+
I thought this would be straight forward and simple. To save some time, I create a second query to do this work:
SELECT [qryA380].ID, [qryA380].Aircraft, MIN([qryA380].Route.ID) AS MinRoute, [qryA380].Passengers
FROM [qryA380]
GROUP BY [qryA380].ID, [qryA380].Aircraft, [qryA380].Passengers
But I kept getting a table identical with the table generated by qryA380. It has all the Route.ID on the results.
The Passenger and ID column should be excluded since they have unique values. By using a Subquery, I'm now able to generate the desired results:
SELECT [qryA380].*
FROM (
SELECT MIN([qryA380].Route.ID) AS MinRoute
FROM [qryA380]
) tblMinRoute
INNER JOIN [qryA380]
ON [qryA380].Route.ID = tblMinRoute.MinRoute
Try this
SELECT [qryA380].*
FROM [qryA380]
WHERE [qryA380].Route.ID = (
SELECT min(Route.ID)
FROM [qryA380]
)

MS Access SQL query from 3 tables

I have 3 tables shown below in MS Access 2010:
Table: devices
id | device_id | Company | Version | Revision |
-----------------------------------------------
1 | dev_a | Almaras | 1.5.1 | 0.2A |
2 | dev_b | Enigma | 1.5.1 | 0.2A |
3 | dev_c | Almaras | 1.5.1 | 0.2C |
*Field: device_id is Primary Key Unique String
*Field ID is just an auto-number column
Table: activities
id | act_id | act_date | act_type | act_note |
------------------------------------------------
1 | dev_a | 07/22/2013 | usb_axc | ok |
2 | dev_a | 07/23/2013 | usb_axe | ok | (LAST ROW for dev_a)
3 | dev_c | 07/22/2013 | usb_axc | ok | (LAST ROW for dev_c)
4 | dev_b | 07/21/2013 | usb_axc | ok | (LAST ROW for dev_b)
*Field: act_id contains device_id; NOT UNIQUE
*Field ID is just an auto-number column
Table: matrix
id | mat_id | tc | ts | bat | cycles |
-----------------------------------------
1 | dev_a | 2811 | 10 | 99 | 200 |
2 | dev_a | 2911 | 10 | 97 | 400 |
3 | dev_a | 3007 | 10 | 94 | 600 |
4 | dev_a | 3210 | 10 | 92 | 800 | (LAST ROW for dev_d)
5 | dev_b | 1100 | 5 | 98 | 100 |
6 | dev_b | 1300 | 8 | 93 | 200 |
7 | dev_b | 1411 | 11 | 90 | 300 | (LAST ROW for dev_b)
8 | dev_c | 4000 | 27 | 77 | 478 | (LAST ROW for dev_c)
*Field: mat_id contains device_id; NOT UNIQUE
*Field ID is just an auto-number column
Is there any way to query tables to get results as shown below (each device from devices and only last row added [see example output table] from each of the other two tables):
Query Results:
device_id | Company | act_date | act_type | bat | cycles |
------------------------------------------------------------
device_a | Almaras | 07/23/2013 | usb_axe | 92 | 800 |
device_b | Enigma | 07/21/2013 | usb_axc | 90 | 300 |
device_c | Almaras | 07/22/2013 | usb_axc | 77 | 478 |
Any ideas? Thank you in advance for reading and helping me out :)
I think is what you want,
SELECT a.device_id, a.Company,
b.act_date, b.act_type,
c.bat, c.cycles
FROM ((((devices AS a
INNER JOIN activities AS b
ON a.device_id = b.act_id)
INNER JOIN matrix AS c
ON a.device_id = c.mat_id)
INNER JOIN
(
SELECT act_id, MAX(act_date) AS max_date
FROM activities
GROUP BY act_id
) AS d ON b.act_id = d.act_id AND b.act_date = d.max_date)
INNER JOIN
(
SELECT mat_id, MAX(tc) AS max_tc
FROM matrix
GROUP BY mat_id
) AS e ON c.mat_id = e.mat_id AND c.tc = e.max_tc)
The subqueries: d and e separately gets the latest row for every act_id.
Try
SELECT devices.device_id, devices.Company, activities.act_data, activities.act_type, matrix.bat, matrix.cycles
FROM devices
LEFT JOIN activities
ON devices.device_id = activities.act_id
LEFT JOIN matrix
ON devices.device_id = matrix.mat_id;
What do you consider the "last" row in Matrix?
You need to do something like
WHERE act_date in (SELECT max(a.act_date) from activities a where a.mat_id=d.device_id GROUP BY a.mat_id)
and something similar for the join to matrix.

Is it Possible to Join these 2 Tables

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