SQL CASE WHEN Date - sql

I am trying to create a table that gives me the number of users that have accessed an app within the last 3 months as follows:
last 3 months: (number)
last 2 months: (number)
last month: (number)
the number is coming from another table result that has the value day_p which indicates the day the unique user accessed the app. I just want to place them within the month frame. Below is the code I am trying to run, but I keep getting an error that name is expected, but I have named them as 'Three_Month', 'Two_Month', 'Last_Month'.
CREATE TABLE Last_Access AS
SELECT
count(CASE WHEN t1.day_p BETWEEN '20210518' AND '20210618' THEN 1 END) AS 'THREE_MONTH',
count(CASE WHEN t1.day_p BETWEEN '20210619' AND '20210718' THEN 1 END) AS 'TWO_MONTH',
count(CASE WHEN t1.day_p BETWEEN '20210719' AND '20210819' THEN 1 END) AS 'LAST_MONTH',
End
FROM Result AS t1;
Any suggestions / tips would be appreciated! :)

To create a TABLE you need to give your variables names. You could also attach a label to the variable if you wanted. You don't need to include the label= keyword, but I find it makes it clearer what the string is there for.
CREATE TABLE Last_Access AS
SELECT
count(CASE WHEN t1.day_p BETWEEN '20210518' AND '20210618' THEN 1 END)
AS THREE_MONTH LABEL='THREE_MONTH'
,count(CASE WHEN t1.day_p BETWEEN '20210619' AND '20210718' THEN 1 END)
AS TWO_MONTH LABEL='TWO_MONTH'
FROM Result AS t1
;
PS Don't put continuation characters at the end of the lines. Places them at the start of the line and you will be less likely to include an extra one like in your example because they will be more visible to the humans reading the code.

Related

Counting how many times one specific value changed to another specific value in order of date range and grouped by ID

I have a table like below where I need to query a count of how many times each ID went from specifically 'Waste Sale' in one value to 'On Stop' in the very next value based on ascending date and if there are no instances of this, the count will be 0
ID
Stage name
Stage Changed Date
1
Waste Sale
06-05-2022
1
On Stop
08-06-2022
1
Cancelled
09-02-2022
2
Waste Sale
06-05-2022
2
On Stop
07-05-2022
2
Waste Sale
08-06-2022
2
On Stop
10-07-2022
3
Cancelled
10-07-2022
3
On Stop
11-07-2022
The result I would be looking for based on the above table would be something like this:
ID
Count of 'Waste Sales to On Stops'
1
1
2
2
3
0
ID 1 having a count of 1 because there was one instance of 'Waste Sale' changing to 'On Stop' in the very next value based on date range
ID 3 having a count of 0 because even though the stage name changed to 'On Stop' the previous value based on date range wasn't 'Waste Sale'.
I have a hunch I would have to use something like LEAD() and GROUP BY/ ORDER BY but since I'm so new to SQL would really appreciate some help on the specific syntax and coding. Any version of SQL is okay.
We can use window function lead to take a peek at the next value of the query result.
select distinct id,
(
select count(*)
from
(
select *,
lead(stage_name)
over(
partition by id
order by stage_changed_date)
as stage_next
from sales s2
) s3
where s3.id = s1.id
and s3.stage_name = 'waste sale'
and s3.stage_next = 'on stop'
) as count_of_waste_sales_to_on_stop
from sales s1
order by id;
Query above uses lead(stage_name) over(partition by id order by stage_changed_date) to get the next stage_name in the query result while segregating it by id and order it based on stage_changed_date. Check the query on DB Fiddle.
Note:
I have no experience in zoho, so i'm unsure if the query will 100% works or not. They said it supported ansi-sql, however there might some differences with MySQL due to reasons.
The column names are not the exact same with op question due to testing only done using DB Fiddle.
There might better query out there waiting to be written.

How to classify rows having one or more related records

I need to add the additional column called rank_2 which will show whether the source has more than 1 source_ids.
So, I need to get this result:
I don't know how to write a query to get rank_2, which will contain 1 when the source has the only source_id (like the source "b") and contain 2 when the source has 2 or more source_ids (like the source "a").
Assuming window functions are available you can use a query like so:
select *
, case when count(*) over (partition by date, source_name) = 1 then 1 else 2 end as rank_2
from t
With the count function you will be able to resolve this problem:
, count(source_id) as rank_2
Don't forget to group by date, source_name, source_id.
I only don't understand why source_id 11 needs to get value 1 as it is also shown two times in the table.

Select Rows and Flag Column if value found

i need help for creating a query
Current situation:
The output table contains Ids and levels. Each Id can appear several times.
Problem:
Now I want to know if level 1 appears for an id, if so I want to mark it as number 1. If an Id has only level 2 or zero just mark it as number 0.
The output can be taken from the table below.
Use aggregation:
select id,
max(case when level = 1 then 1 else 0 end) as flag
from t
group by id;

Qualifying a column in a SQL select statement

I'm looking to generate a query that pulls from several tables. Most are rather straightforward and I can pull a value from a table directly but there is one table that is pivoted so that the value I want depends on the value in another column.
The table looks like the below:
ID Condition Value
1 Stage1 6
2 Stage2 9
3 Stage3 5
4 Stage4 2
So I'm looking to write a query that essentially "qualifies" the value I want by telling the table which condition.
An example of my SQL:
Select Attribute1, Stage1Value, Stage2Value, Stage3Value
From attribute, stage
where attribute = project1
So I can't just pull the "Value" column as it needs to know which stage in the query.
There are 30 columns I am trying to pull - of which 13 fall into this category. Thanks for any help you can provide.
So, you want conditional aggregation something :
select a.<col>,
sum(case when s.Condition = 'Stage1' then s.value else 0 end),
. . .
sum(case when s.Condition = 'Stage4' then s.value else 0 end)
from attribute a inner join
stage s
on s.<col> = a.<col>
group by a.<col>

SQL (SQLite) count for null-fields over all columns

I've got a table called datapoints with about 150 columns and 2600 rows. I know, 150 columns is too much, but I got this db after importing a csv and it is not possible to shrink the number of columns.
I have to get some statistical stuff out of the data. E.g. one question would be:
Give me the total number of fields (of all columns), which are null. Does somebody have any idea how I can do this efficiently?
For one column it isn't a problem:
SELECT count(*) FROM datapoints tb1 where 'tb1'.'column1' is null;
But how can I solve this for all columns together, without doing it by hand for every column?
Best,
Michael
Building on Lamak's idea, how about this idea:
SELECT (N * COUNT(*)) - (
COUNT(COLUMN_1)
+ COUNT(COLUMN_2)
+ ...
+ COUNT(COLUMN_N)
)
FROM DATAPOINTS;
where N is the number of columns. The trick will be in making the summation series of COUNT(column), but that shouldn't be too terrible with a good text editor and/or spreadsheet.
i don't think there is an easy way to do it. i'd get started on the 150 queries. you only have to replace one word (column name) each time.
Well, COUNT (and most aggregations funcions) ignore NULL values. In your case, since you are using COUNT(*), it counts every row in the table, but you can do that on any column. Something like this:
SELECT TotalRows-Column1NotNullCount, etc
FROM (
SELECT COUNT(1) TotalRows,
COUNT(column1) Column1NotNullCount,
COUNT(column2) Column2NotNullCount,
COUNT(column3) Column3NotNullCount ....
FROM datapoints) A
To get started it's often helpful to use a visual query tool to generate a field list and then use cut/paste/search/replace or manipulation in a spreadsheet program to transform it into what is needed. To do it all in one step you can use something like:
SELECT SUM(CASE COLUMN1 WHEN NULL THEN 1 ELSE 0 END) +
SUM(CASE COLUMN2 WHEN NULL THEN 1 ELSE 0 END) +
SUM(CASE COLUMN3 WHEN NULL THEN 1 ELSE 0 END) +
...
FROM DATAPOINTS;
With a visual query builder you can quickly generate:
SELECT COLUMN1, COLUMN2, COLUMN3 ... FROM DATAPOINTS;
You can then replace the comma with all the text that needs to appear between two field names followed by fixing up the first and last fields. So in the example search for "," and replace with " WHEN NULL 1 ELSE 0 END) + SUM(CASE " and then fix up the first and last fields.