JOINing two sub-queries with calculated fields - sql

I have two tables containing info about the production of two widgets. Table1 looks like this:
Table2 looks like this:
I want to calculate the average production of each widget and display by the country code (ADM0_A3), so that the results would look something like this (not that bothered about missing data at this stage eg. BWA has no production of widget1)
ADM0_A3 w1avg w2avg
DZA 50000 3450000
AGO 86000 40000
BWA blank 0
CMR 3500 blank
The MS ACCESS SQL query I am using is here:
SELECT Z.ccode, Z.ave_w1, A.ave_w2
FROM
(
SELECT X.ADM0_A3 as ccode, 0.02 * X.sum_w1 / X.n_w1 AS ave_w1
FROM
(
SELECT t1.ADM0_A3, SUM(t1.production) AS sum_w1, COUNT(t1.production) as n_w1
FROM Table1 t1
GROUP BY t1.ADM0_A3
) X
) Z
JOIN
(
SELECT Y.ADM0_A3, 0.025 * Y.sum_w2 / Y.n_w2 AS ave_w2
FROM
(
SELECT t2.ADM0_A3, SUM(t2.production) AS sum_w2, COUNT(t2.production) as n_w2
FROM Table2 t2
GROUP BY t2.ADM0_A3
) Y
) A
ON A.ADM0_A3 = Z.ccode
I checked the sub-queries and they work OK. However, when I try to JOIN the queries I get this error message "Syntax error in FROM clause". I think the solution is something fairly simple but I just can't see it so would appreciate any suggestions. Thanks in advance!

You can try doing this:
SELECT adm0_a3, MAX(w1avg) as w1avg, MAX(w2avg) as w2avg
FROM (SELECT t1.ADM0_A3, AVG(t1.production) * 0.02 as w1avg, NULL as w2avg
FROM Table1 as t1
GROUP BY t1.ADM0_A3
UNION ALL
SELECT t2.ADM0_A3, NULL, AVG(t2.production) * 0.02 as w1avg
FROM Table1 as t2
GROUP BY t2.ADM0_A3
) as t
GROUP BY adm0_a3;
I'm not sure if all versions of MS Access support UNION ALL in the FROM clause. If not, you can work around that using a view.

Related

Using the results of one SQL query in another query (Athena)

I'm a bit stuck on how can do this so hoping someone can point me in the right direction.
I have this simple query:
SELECT acchl.is_current,
acchl.aircraft_registration_number,
acchl.aircraft_transponder_code
FROM fleets.aircraft_all_history_latest acchl
WHERE acchl.is_current = true
Which I then want to use the results from this query to find all the duplicate aircraft transponder codes along with the aircraft registration numbers with something like a self join to fetch the actual rows that may have duplicate values using something like this:
select s.id, s.col_maybe_dups
from sometab s
join (select col_maybe_dups as cd
from sometab
group by cd
having count(*) > 1) x
on x.cd = s.col_maybe_dups;
Looks good!
You could WITH it too...
WITH data as (
SELECT acchl.is_current,
acchl.aircraft_registration_number,
acchl.aircraft_transponder_code
FROM fleets.aircraft_all_history_latest acchl
WHERE acchl.is_current
)
select * from data
where aircraft_transponder_code in
(select aircraft_transponder_code
from data
group by 1
having count(*) > 1
)

SQL if statement to select items form different tables

I am creating a new table joining 3 different tables. The problem is that I have some data that I want to select for other_info divided into two different tables. table_1 has preference over table_2, but it is possible that in table_1 are missing values. So, I want to select the value of box if it's not empty from table_1 and select it from table_2 if the value in table_1 does not exist.
This is the code I have very simplified, but I think it's enough to see what I want to do. I've written an IF ... ELSE statement inside a with, and this is the error I get:
Syntax error: Expected "(" or keyword SELECT or keyword WITH but got keyword IF at [26:5]
Besides, I've tried different things inside the conditional of the if, but none of them is what I expect. Here is the code:
CREATE OR REPLACE TABLE `new_table`
PARTITION BY
Current_date
AS (
WITH info AS (
SELECT
Date AS Day,
Box,
FROM
`table_1`
),
other_info AS (
IF (...)
BEGIN{
SELECT
Date AS Day,
Box
FROM
`table_1`}
END
ELSE
BEGIN{
SELECT
Date AS Day,
Box
FROM
`table_2`}
END
)
SELECT
Date
Box
Box_description
FROM
`table_3`
LEFT JOIN info(Day)
LEFT JOIN other_info(Day)
)
You're not going to be able to embed an IF within a CTE or a Create-Table-As.
An alternative structure can be to union two queries with mutually exclusive WHERE clauses... (Such that only one of the two queries ever returns anything.)
For example, if the code below, something is checked for being NULL or NOT NULL, and so only one of the two can ever return data.
WITH
info AS
(
SELECT
Date AS Day,
Box,
FROM
`table_1`
),
other_info AS
(
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
THIS BIT
--------------------------------------------------------------------------------
SELECT
Date AS Day,
Box
FROM
`table_1`
WHERE
(SELECT MAX(x) FROM y) IS NULL
UNION ALL
SELECT
Date AS Day,
Box
FROM
`table_2`
WHERE
(SELECT MAX(x) FROM y) IS NOT NULL
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
)
SELECT
Date
Box
Box_description
FROM
`table_3`
LEFT JOIN info(Day)
LEFT JOIN other_info(Day)
In stead of the if..., you could do something like this (in MySQL):
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2 WHERE `date` NOT IN (SELECT `date` FROM table1)
I am not sure (as in: I did not test), but I do think this is also possible in google-bigquery
see: DBFIDDLE

Subquery with 2 parameters in SQL

I have a table in SQL which looks like this:
[
Now, I want the resultant table based on 2 conditions:
Prev_trans_id should match the transactions_ID
Only those entries should come where mod of Amount value is not equal.
The resultant table should like this:
SO, in the resultant table, I dont want row with Transcation_ID as 104 since the mod of amount is same. $1 was paid and $1 was refunded.
I was able to do 1st part of it but not able to do 2nd part as I am new to SQL. This is my code for the 1st part:
select * from sample_table
where prev_trans_id in
(select transaction_id from sample_table)
If I can get the 2nd condition also incorporated in the same query, it would be very helpful.
Use a JOIN, not IN
SELECT t1.*
FROM sample_table AS t1
JOIN sample_table AS t2
ON t1.prev_trans_id = t2.transaction_id AND t1.amount != -1 * t2.amount
BTW, it's not mod of the amounts, it's the negation of the amounts that you want to compare.
There's no need to use a subquery here as it can be achieved with a basic select ... from ... where ... query on table1 and table2. Please see the query below:
select table2.*
from sample_table table1, sample_table table2
where table1.transaction_id = table2.prev_trans_id
and (table1.amount - table2.amount) <> 0

SQL Logic: Finding Non-Duplicates with Similar Rows

I'll do my best to summarize what I am having trouble with. I never used much SQL until recently.
Currently I am using SQL Server 2012 at work and have been tasked with trying to find oddities in SQL tables. Specifically, the tables contain similar information regarding servers. Kind of meta, I know. So they each share a column called "DB_NAME". After that, there are no similar columns. So I need to compare Table A and Table B and produce a list of records (servers) where a server is NOT listed in BOTH Table A and B. Additionally, this query is being ran against an exception list. I'm not 100% sure of the logic to best handle this. And while I would love to get something "extremely efficient", I am more-so looking at something that just plain works at the time being.
SELECT *
FROM (SELECT
UPPER(ta.DB_NAME) AS [DB_Name]
FROM
[CMS].[dbo].[TABLE_A] AS ta
UNION
SELECT
UPPER(tb.DB_NAME) AS [DB_Name]
FROM
[CMS].[dbo].[TABLE_B] as tb
) AS SQLresults
WHERE NOT EXISTS (
SELECT *
FROM
[CMS].[dbo].[TABLE_C_EXCEPTIONS] as tc
WHERE
SQLresults.[DB_Name] = tc.DB_NAME)
ORDER BY SQLresults.[DB_Name]
One method uses union all and aggregation:
select ab.*
from ((select upper(name) as name, 'A' as which
from CMS.dbo.TABLE_A
) union all
(select upper(name), 'B' as which
from CMS.dbo.TABLE_B
)
) ab
where not exists (select 1
from CMS.dbo.TABLE_C_EXCEPTION e
where upper(e.name) = ab.name
)
having count(distinct which) <> 2;
SQL Server is case-insensitive by default. I left the upper()s in the query in case your installation is case sensitive.
Here is another option using EXCEPT. I added a group by in each half of the union because it was not clear in your original post if DB_NAME is unique in your tables.
select DatabaseName
from
(
SELECT UPPER(ta.DB_NAME) AS DatabaseName
FROM [CMS].[dbo].[TABLE_A] AS ta
GROUP BY UPPER(ta.DB_NAME)
UNION ALL
SELECT UPPER(tb.DB_NAME) AS DatabaseName
FROM [CMS].[dbo].[TABLE_B] as tb
GROUP BY UPPER(tb.DB_NAME)
) x
group by DatabaseName
having count(*) < 2
EXCEPT
(
select DN_Name
from CMS.dbo.TABLE_C_EXCEPTION
)

Getting SUM from 2 different tables into one result

I have been trying to get this to work for 12 hrs now and I cannot :-( Can someone please show me how I can get the ssnumber to group and get the total for each ssnumber.
Here is what I have now. In Table number 1 I have this code
SELECT
UNIT_NO, SUM(RATEB) AS TOTALRTE
FROM TABLE1
WHERE
TRUCK_PAID = 1
AND PICK_UP_DATE >= '(fromdate)'
AND PICK_UP_DATE <= '(todate)'
GROUP BY
UNIT_NO
ORDER BY
UNIT_NO
But table number 2 is where the ssnumber column is, so what I'm trying to do is the rateB sum from all of the loads for each unit_no and then group them and then go into table number 2 and group the ssnumber with the unit number from table number 1 and sum the rateB from table number 1.
Something like this (see below) but its not working :-(
SELECT
UNIT_NO, SUM(RATEB)
FROM
TABLE1
WHERE
TRUCK_PAID = 1
AND PICK_UP_DATE >= '(fromdate)'
AND PICK_UP_DATE <= '(todate)'
GROUP BY
UNIT_NO
JOIN
TABLE TABLE1.UNIT_NO = TABLE2.UNIT_NO GROUP BY TABLE2.SS_NUM
or
SELECT
UNIT_NO, SUM(RATEB) AS TOTALRATE
FROM
TABLE1
GROUP BY
UNIT_NO
JOIN
TRUCKS ON (TABLE1.UNIT_NO = TABLE2.UNIT_NO)
GROUP BY
TABLE2.SSNUMBER
Thank you guys so much for any help...
As requested, it is hard to really understand what you are trying to accomplish without more info about table2 and maybe an example of what you are expecting. However, what I got from your description is that you are trying to accomplish something like this?
SELECT UNIT_NO, TOTALRTE, TOTALLDSRTE
FROM
(
SELECT UNIT_NO,SUM(RATEB) AS TOTALRTE
FROM LOADS
GROUP BY UNIT_NO
) AS tbl1
JOIN
(
SELECT SS_NUM, SUM(RATEB) AS TOTALLDSRTE
FROM LOADS
GROUP BY SS_NUM
) AS tbl2
ON tbl1.UNIT_NO = tbl2.SS_NUM
I would suggest instead of getting data from two select queries in one select query, try to fetch them as separate queries. This saves a lot of time. That, or you can create a table for the result and update the result of each query into the table.