Creating view in mysql for a group of rows - mysql

I have a mysql table with the following columns
1. id - int, auto increasing;
2. loc_id - int;
3. group_id - int;
4. target_date - int (epoch timestamp for each date at 00:00);
5. required - int;
6. actual - int;
7. updated_on;
Records in the table will be inserted in blocks, where the number of inserted rows is equal to the number of groups (referenced by group_id). The number of groups is 3, i.e. each transaction will insert 3 rows:
loc_id + target_date + updated_on will be the same for each of the 3 rows;
the group_id will be 1 to 3 for each row;
required and actual will be specific for each row.
My question is: how to create a view so each block of 3 rows is represented as a single row in a table with columns as follows:
1. loc_id,
2. target_date,
3. required_for_group1,
4. actual_for_group1,
5. required_for_group2,
6. actual_for_group2,
7. required_for_group3,
8. actual_for_group3
9. updated_on
Many thanks in advance for your help!
With the example above is it possible to find which record is the latest for each loc_id/target_date if the cut-off point is 03:00AM for each target_date (which is always epoch at 00:00)? Something like an extra column to say "latest" for the entry "closest" to (target_date+10800). i tried adding a column "case when min((target_date+10800)-updated_on) then "latest" else 0 end", but did not quite make it work..

You can do get the results you want using conditional aggregation:
select loc_id, target_date,
max(case when group_id = 1 then required end) as required_1,
max(case when group_id = 1 then actual end) as actual_1,
max(case when group_id = 2 then required end) as required_2,
max(case when group_id = 2 then actual end) as actual_2,
max(case when group_id = 3 then required end) as required_3,
max(case when group_id = 3 then actual end) as actual_3,
updated_on
from table t
group by loc_id, target_date, updated_on;
You can put this statement into a view by putting create view <viewname> as before it.

Related

SQL - how to add a value with a condition to a selection?

I have the following table structure:
name
value
success
name 1
10
0
name 2
20
0
name 2
30
1
And my query is:
SELECT name, SUM(value) as valueTotal FROM TableName GROUP BY name
The result is:
name
valueTotal
name 1
10
name 2
50
Now I want to add a new column which will contain the sum of only successful rows. But if I add this condition, it will apply to all selected fields:
SELECT name, SUM(value) as valueTotal, SUM(value) as successValueTotal FROM TableName WHERE success = 1 GROUP BY name
Here is the result I want to get:
name
valueTotal
successValueTotal
name 1
10
0
name 2
50
30
How can I add a field with a separate condition that does not affect the main query? Thx)
You can use the SUM function with a conditional aggregation on whether success is 1 or not. When success is 1, then take the value of the value field, otherwise sum up 0.
SELECT name,
SUM(value) AS valueTotal,
SUM(IF(success = 1, value, 0)) AS successValueTotal
FROM TableName
GROUP BY name
Try it here.
This is the typical use case for CASE WHEN:
SELECT name,
SUM(value) AS valueTotal,
SUM(CASE WHEN success = 1 THEN value ELSE 0 END) AS successValueTotal
FROM TableName
GROUP BY name
You can (like lemon showed) also use an if clause in MYSQL. This is a bit shorter, but the query will not work on every DB while CASE WHEN does. So I think both is fine.

Count of past instances in an appended table

This is my desired output:
CampaignName CampaignDate UsersTargeted CountOfUsersBought
2x1 2018-11-24 1 (UserId 2) 1 (UserId 2)
3x2 2018-11-25 2 (Both) 1 (UserId 1)
'CountOfUsersBought' I want it to be Amongst All Targeted Users.
And the Table (Updated Daily) from where I get the data to fill the previous output has the following structure:
UserId EligibleForOffer(0,1) BoughtToday(0,1) Timestamp
1 0 0 2018-11-24
1 1 0 2018-11-25
1 1 1 2018-11-26
1 0 0 2018-11-27
2 1 0 2018-11-24
2 1 1 2018-11-25
2 1 0 2018-11-26
2 0 1 2018-11-27
I want to store on the variable 'CountOfUsersBought' the count of all the users that actually bought, not only today but all time. How would you go about doing this query?
Please note that users also buy without an offer, so I only want to count the past instances WHERE EligibleForOffer = 1 AND BoughtToday = 1 AND Timestamp <= 'CampaignDate'+ 1 day
I know for another table the users that are targeted for each campaign, I just want to keep for more than 'today' the count of users that took the offer that was given to them.
You can GROUP BY dates and use SUM the find how many users eligible for campaigns and use CASE to do your conditions. And bonus is MIN to find which specific user related with the condition is only one user match.
CREATE TABLE Campain
(
UserId INT
,EligibleForOffer BIT
,BoughtToday BIT
,Timestamp DATE
)
INSERT INTO Campain
VALUES
(1,0,0,'2018-11-24')
,(1,1,0,'2018-11-25')
,(1,1,1,'2018-11-26')
,(1,0,0,'2018-11-27')
,(2,1,0,'2018-11-24')
,(2,1,1,'2018-11-25')
,(2,1,0,'2018-11-26')
,(2,0,1,'2018-11-27')
SELECT Timestamp
,SUM(CAST(EligibleForOffer AS INT)) NumberOfUsersTargeted
,CASE WHEN SUM(CAST(EligibleForOffer AS INT))=1 THEN 'UserId-'+CAST(MIN(UserId) AS VARCHAR) WHEN SUM(CAST(EligibleForOffer AS INT))>1 THEN 'Multiple Users(Both)' ELSE 'No Target' END UsersTargetedDetail
,SUM(CAST(BoughtToday AS INT)) NumberOfBought
,CASE WHEN SUM(CAST(BoughtToday AS INT))=1 THEN 'UserId-'+CAST(MIN(UserId) AS VARCHAR) WHEN SUM(CAST(BoughtToday AS INT))>1 THEN 'Multiple Users(Both)' ELSE 'No Buying' END BoughtDetail
FROM Campain
GROUP BY Timestamp

Setting priority in SQL

We have a table test in which we have status_cd as one of the column. Status Code can have three value - Prelim, Approved and confirmed.
I have to write a query in such a way that it should fetch the record for confirmed status cd. If confirmed status cd is not present, then fetch for Approved, if approved is not present, fetch for prelim, if prelim is also not present, fetch for null
id rule_id status_cd
1 1 prelim
2 1 null
3 1 approved
in above example, the query should return approved for rule_id=1
Try this way:
SELECT T1.*
FROM test T1 JOIN
(SELECT *,CASE status_cd WHEN 'confirmed' THEN 1
WHEN 'approved' THEN 2
WHEN 'prelim' THEN 3
ELSE 4 END AS Rank
FROM test) T2 ON T1.id=T2.id AND T1.Rule_id =T2.Rule_id
ORDER BY T2.Rank
LIMIT 1
Result:
ID RULE_ID STATUS_CD
3 1 approved
Sample result in SQL Fiddle.
Use the values '3 Confirmed','2 Approved', '1 Prelim' and '0 Null' or just use a default value of zero in a numerical field and set the value to 1, 2, 3 as the rule progresses (much faster execution, but avoid the null either way by using a default value of '0 Null' in the field if you keep a string implementation).
Then fetch the records with this query:
SELECT status_cd FROM YourTableName WHERE rule_id=1 ORDER BY status_cd DESC;
The first row of the query will always contain the answer you want. Additionally, the other rows will be there to confirm that all the other steps were present, etc. if you want to look at those rows too. If you know you only need the one row, then use
SELECT TOP 1 status_cd FROM ... (the rest is the same)

mysql count distinct value

I have trouble wondering how do I count distinct value. using if on the select column
I have SQLFIDDLE here
http://sqlfiddle.com/#!2/6bfb9/3
Records shows:
create table team_record (
id tinyint,
project_id int,
position varchar(45)
);
insert into team_record values
(1,1, 'Junior1'),
(2,1, 'Junior1'),
(3,1, 'Junior2'),
(4,1, 'Junior3'),
(5,1, 'Senior1'),
(6,1, 'Senior1'),
(8,1, 'Senior2'),
(9,1, 'Senior2'),
(10,1,'Senior3'),
(11,1, 'Senior3'),
(12,1, 'Senior3')
I need to count all distinct value, between Junior and Senior column.
all same value would count as 1.
I need to see result something like this.
PROJECT_ID SENIOR_TOTAL JUNIOR_TOTAL
1 3 3
mysql query is this. but this is not a query to get the result above.
SELECT
`team_record`.`project_id`,
`position`,
SUM(IF(position LIKE 'Senior%',
1,
0)) AS `Senior_Total`,
SUM(IF(position LIKE 'Junior%',
1,
0)) AS `Junior_Total`
FROM
(`team_record`)
WHERE
project_id = '1'
GROUP BY `team_record`.`project_id`
maybe you could help me fix my query above to get the result I need.
thanks
I think you want this:
SELECT
project_id,
COUNT(DISTINCT CASE when position LIKE 'Senior%' THEN position END) Senior_Total,
COUNT(DISTINCT CASE when position LIKE 'Junior%' THEN position END) Junior_Total
FROM team_record
WHERE project_id = 1
GROUP BY project_id
The CASE will return a null if the WHEN is false (ie ELSE NULL is the default, which I omitted for brevity), and nulls aren't counted in DISTINCT.
Also, unnecessary back ticks, brackets and qualification removed.

mySQL count occurances of value on multiple fields. How?

I have a table with 5 fields. Each field can store a number from 1 - 59.
Similar to countif in Excel, how do I count the number of times a number from 1 - 59 shows up in all 5 fields?
Here's an example for the count of occurances for the number 1 in all five fields:
SELECT SUM(pick_1 = 1 OR pick_2 = 1 OR pick_3 = 1 OR pick_4 = 1 OR pick_5 = 1) AS total_count_1
FROM tbldraw
Hopefully I made sense.
There was an answer here that had a solution. I think this is just a variation.
Step1: Create a numbers table (1 field, called id, 59 records (values 1 -59))
Step2:
SELECT numbers_table.number as number
, COUNT(tbldraw.pk_record)
FROM numbers_table
LEFT JOIN tbldraw
ON numbers_table.number = tbldraw.pick_1
OR numbers_table.number = tbldraw.pick_2
OR numbers_table.number = tbldraw.pick_3
OR numbers_table.number = tbldraw.pick_4
OR numbers_table.number = tbldraw.pick_5
GROUP BY number
ORDER BY number
How about a two step process? Assuming a table called summary_table ( int id, int ttl), for each number you care about...
insert into summary_table values (1,
(select count(*)
from table
where field1 = 1 or field2 = 1 or field3 = 1 or field4 = 1 or field5 = 1))
do that 59 times, once for each value. You can use a loop in most cases. Then you can select from the summary_table
select *
from summary_table
order by id
That will do it. I leave the coversion of this SQL into a stored procedure for those that know what database is in use.
The ALL() function, which returns true if the preceding operator is true for all parameters, makes the query particularly elegant and succinct.
To find the count a particular number (eg 3):
select count(*)
from tbldraw
where 3 = all (pick_1, pick_2, pick_3, pick_4, pick_5)
To find the count of all such numbers:
select pick_1, count(*)
from tbldraw
where pick_1 = all (pick_2, pick_3, pick_4, pick_5)
group by pick_1