Trouble with SQL UNION operation - sql

I have the following table:
I am trying to create an SQL query that returns a table that returns three fields:
Year (ActionDate), Count of Built (actiontype = 12), Count of Lost (actiontype = a few different ones)
Bascially, ActionType is a lookup code. So, I'd get back something like:
YEAR CountofBuilt CountofLost
1905 30 18
1929 12 99
1940 60 1
etc....
I figured this would take two SELECT statements put together with a UNION.
I tried the following below but it only spits back two columns (year and countbuilt). My countLost field doesn't appear
My sql currently (MS Access):
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countBuilt
FROM ...
WHERE ((tblHist.ActionType)=12)
GROUP BY tblHist.ActionDate
UNION
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countLost
FROM ...
WHERE (((tblHist.ActionType)<>2) AND
((tblHist.ActionType)<>3))
GROUP BY tblHist.ActionDate;

Use:
SELECT h.actiondate,
SUM(IIF(h.actiontype = 12, 1, 0)) AS numBuilt,
SUM(IIF(h.actiontype NOT IN (2,3), 1, 0)) AS numLost
FROM tblHist h
GROUP BY h.actiondate

You should not use UNION for such queries. There are many ways to do what you want, for example
Updated to fit access syntax
SELECT tblHist.ActionDate,
COUNT(SWITCH(tblHist.ActionType = 12,1)) as countBuilt,
COUNT(SWITCH(tblHist.ActionType <>1 OR tblHist.ActionType <>2 OR ...,1)) as countLost
FROM ..
WHERE ....
GROUP BY tblHist.ActionDate

Related

Applying advanced filter in Power BI DAX, from a different table

I have the following tables:
Episodes:
Clients:
My DAX calculation sums up [Days_epi] unique values, from Episodes tbl, grouping them by [ProgramID_epi], [EpisodeID_epi], [ClientID_epi].
So, the SUM of [Days_epi] = 3 + 5 + 31 + 8 + 15 + 20 + 10 = 92
Here is my working code for this:
DaysSUM =
CALCULATE (
SUMX (
SUMMARIZE (
'Episodes',
'Episodes'[EpisodeID_epi],
'Episodes'[ProgramID_epi],
'Episodes'[ClientID_epi],
'Episodes'[Days_epi]
),
'Episodes'[Days_epi]
),
FILTER (
'Episodes',
'Episodes'[Category_epi] = "Homeless"
)
)
I need to add two advanced filters to the calculation above:
Filter 1 should ONLY KEEP records in Episodes, if the records in the Clients have the difference between [DischDate_clnt] and [AdmDate_clnt] >= 365.
Filter 1 in SQL statement is
DATEDIFF(DAY, [AdmDate_clnt], [DischDate_clnt]) >= 365)
After that, Filter 2 should ONLY KEEP records in Episodes, if the records in the Clients have
[Date_clnt] >= [AdmDate_clnt] + 12 months. (12 month after the Admission Date)
Filter 2 in SQL statement is
[Date_clnt] <= DATEADD(MONTH, 12, [[AdmDate_clnt])
So, after applying those two filters I expect the records 6 and 10 of the Episodes tbl must be excluded (filtered out), because the records 2 and 3 of the Clients tbl (highlighted in green) are not satisfied my Filter 1 / Filter 2.
Here is the final Episodes dataset I should have (without the 2 records in red):
I was starting to update my DAX code as the following (below).
But keep receiving error "Parameter is not the correct type"
enter
DaysSUM_Filters =
CALCULATE (
SUMX (
SUMMARIZE (
'Episodes',
'Episodes'[EpisodeID_epi],
'Episodes'[ProgramID_epi],
'Episodes'[ClientID_epi],
'Episodes'[Days_epi]
),
'Episodes'[Days_epi]
),
FILTER (
'Episodes',
'Episodes'[Category_epi] = "Homeless"
), TREATAS(DATEDIFF('Clients'[AdmDate_clnt],
'Clients'[DischDate_clnt], DAY)>=365,
'Clients'[Date_clnt])
)
Not exactly sure how to set those 2 filters correctly in DAX Power BI, as I
am relatively new to it.
Please help!
I can't say about all the case. But what is obvious is that you use TREATAS in a wrong way. It works like this TREATAS({"Red", "White", "Blue"}, 'Product'[Color]).
In your case
DATEDIFF('Clients'[AdmDate_clnt],
'Clients'[DischDate_clnt], DAY)>=365
will return TRUE or FALSE value. The first argument of TREATAS - is a column or set of columns not a single value.
You can use the filter like this:
FILTER(
'Clients'
,DATEDIFF(
'Clients'[AdmDate_clnt]
,'Clients'[DischDate_clnt]
,DAY
)>=365
)
This will return you a filtered table.
This may work if your tables are linked.

Adding summary statistics to an existing table in SQL

I am trying to add summary statistics (just total and average) to a table with 21 columns and 7 rows of data, I would like the two rows of summary statistics to start at row 8. I've been trying a query along these lines without any luck:
SELECT *
FROM
( SELECT 1,
weekday, summer_member_total, summer_member_avg_duration, summer_casual_total, summer_casual_avg_duration,
fall_member_total, fall_member_avg_duration, fall_casual_total, fall_casual_avg_duration,
winter_member_total, winter_member_avg_duration, winter_casual_total, winter_casual_avg_duration,
spring_member_total, spring_member_avg_duration, spring_casual_total, spring_casual_avg_duration,
member_total, member_avg_duration, casual_total, casual_avg_duration,
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Summary_Stats`
UNION ALL
SELECT 8,
'TOTAL',
SUM(summer_member_total),
SUM(summer_member_avg_duration),
SUM(summer_casual_total),
SUM(summer_casual_avg_duration),
SUM(fall_member_total),
SUM(fall_member_avg_duration),
SUM(fall_casual_total),
SUM(fall_casual_avg_duration),
SUM(winter_member_total),
SUM(winter_member_avg_duration),
SUM(winter_casual_total),
SUM(winter_casual_avg_duration),
SUM(spring_member_total),
SUM(spring_member_avg_duration),
SUM(spring_casual_total),
SUM(spring_casual_avg_duration),
SUM(member_total),
SUM(member_avg_duration),
SUM(casual_total),
SUM(casual_avg_duration),
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Summary_Stats`
UNION ALL
SELECT 9,
'AVG',
AVG(summer_member_total),
AVG(summer_member_avg_duration),
AVG(summer_casual_total),
AVG(summer_casual_avg_duration),
AVG(fall_member_total),
AVG(fall_member_avg_duration),
AVG(fall_casual_total),
AVG(fall_casual_avg_duration),
AVG(winter_member_total),
AVG(winter_member_avg_duration),
AVG(winter_casual_total),
AVG(winter_casual_avg_duration),
AVG(spring_member_total),
AVG(spring_member_avg_duration),
AVG(spring_casual_total),
AVG(spring_casual_avg_duration),
AVG(member_total),
AVG(member_avg_duration),
AVG(casual_total),
AVG(casual_avg_duration),
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Summary_Stats` )
ORDER BY 1
Any ideas on how to approach this?
As an option to six your issue - replace
SELECT 1,
weekday, summer_
with
SELECT 1,
CAST(weekday AS STRING) weekday , summer_

Using UNION ALL to combine two queries into one table

Trying to combine two queries that find the average value of column 'duration_minutes' broken down into two criteria (column 'member_casual' - for which there are only 2 options 'member' or 'casual'. I have been trying a the following syntax, which does display the data that I want, but in two rows, rather than two columns:
SELECT * FROM(
SELECT AVG(duration_minutes) as cas_avg
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Rides_Merged`
WHERE member_casual = 'casual'
UNION ALL
SELECT AVG(duration_minutes) as mem_avg
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Rides_Merged`
WHERE member_casual = 'member');
Resulting table:
Row
cas_avg
1
40.81073227046788
2
11.345919528176575
How would I combine those to queries so that the result from row 2 would instead display as a column with the header "mem_avg" (the alias that was given in the query)?
How would I combine those to queries so that the result from row 2 would instead display as a column with the header "mem_avg" (the alias that was given in the query)?
try below
SELECT
AVG(IF(member_casual = 'casual', duration_minutes, null) ) as cas_avg,
AVG(IF(member_casual = 'member', duration_minutes, null) ) as mem_avg,
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Rides_Merged`
with output
You would use group by:
SELECT member_casual, AVG(duration_minutes) as cas_avg
FROM `case-study-319921.2020_2021_Trip_Data.2020_2021_Rides_Merged`
GROUP BY member_casual;
If there are more than two types, you may need to add:
member_casual in ('casual', 'member')

Grouping in SQL Hierarchy

I'm still new to SQL and my question here is kinda long. Ok here it is...my task is to calculate the total downtime of machines situated in a particular location. Each machine has parent, children and grandchildren. For eg:
Location:A1
Machine no:A1-100, A1-100-01, A1-100-01-001, A1-200, A1-200-01
(A1-100-01, A1-100-01-001 belongs to A1-100) and (A1-200-01 belongs to A1-200)
This is my SQL query:
select machine_no, downtime from table_name where location='A1'
The output is:
machine_no downtime
A1-100-01 2
A1-100 1.5
A1-200 3
A1-100-01-001 0.5
A2-200-01 1.5
My question is how do I group the children and grandchildren to their parent and display the total downtime of that group? I'm sorry if the question is confusing but basically I want the output to be like this:
machine_no total_downtime
A1-100 4 (total of A1-100,A1-100-01,A1-100-01-001)
A1-200 4.5 (total of A1-200,A1-200-01)
Thank you.
try the following query:
SELECT machine_no, SUM(downtime) as total_downtime
FROM (
SELECT
SUBSTR(machine_no, 1,
CASE WHEN INSTR(machine_no, '-', 1, 2) = 0 THEN LENGTH(machine_no) ELSE INSTR(machine_no, '-', 1, 2)-1 END
) as machine_no, -- this will get the part of machine_no before the second '-' char
downtime
FROM MyTable
WHERE location='A1'
) InnerQuery
GROUP BY machine_no
output:
machine_no total_downtime
A1-100 4
A1-200 4.5
You don't actually need the inner query, but it's more readable then grouping by the SUBSTR(....) expression.
Play with it yourself on sql fiddle
You can use group by along with sum like :
select machine_no, sum(downtime) from table_name where location like 'A1-100%' group by machine_no;

SQL SUM total using 2 tables

I have 2 tables: TBL_EQUIPMENTS and TBL_PROPOSAL.
TBL_PROPOSAL has 3 important columns:
id_proposal
date
discount
TBL_EQUIPMENTS has:
id_equipment
id_proposal
unit_price
quantity
Now I want to know how much (in €) is my proposals for this year, let's say:
For each TBL_PROPOSAL.date > "2013-01-01" I want to use the formula:
result = (TBL_EQUIPMENTS.unit_price * TBL_EQUIPMENTS.quantity) * (100 - TBL_PROPOSAL.discount)
I can do this with one SQL statement?
Yes you can:
select e.unit_price * e.quantity) * (100 - p.discount)
from tbl_Proposal p join
tbl_Equipments e
on p.id_Proposal = e.id_proposal
where date >= '2013-01-01'
The basic syntax is for a join. The p and e are called table aliases. They make the query easier to read (the full table names are rather bulky).
Date operations differ among databases. The last statement should work in most databases. However, you might try one of the following as well:
where year(date) = 2013
where extract(year from date) = 2013