2 Step SQL query according to date - mysql

I have the following structure:
ID CID CAMPAIGN_ID DATE(DATETIME) DEVICE
1 123 88 2012-04-29 07:26:14 PC
2 123 88 2012-04-29 08:46:04 IPHONE
3 555 91 2012-04-29 08:36:04 IPAD
I'm trying to find a way to build a query that will return all the valid CIDs that first used the PC and then used the IPHONE (according to the date specified) under a specified campaign_id.
in the example above CID 123 falls into that category.

As #JohannBlais said in his comment, you need to join the table to itself on the desired criteria and then filter for your chosen campaign:
SELECT `t1`.`CID`
FROM
`tbl` AS `t1`
JOIN `tbl` AS `t2` ON (
`t1`.`CID` = `t2`.`CID`
AND `t1`.`CAMPAIGN_ID` = `t2`.`CAMPAIGN_ID`
AND `t1`.`DATE(DATETIME)` < `t2`.`DATE(DATETIME)`
AND `t1`.`DEVICE` = 'PC'
AND `t2`.`DEVICE` = 'IPHONE'
)
WHERE `t1`.`CAMPAIGN_ID` = #specified_campaign;

Related

How to add subquery to get last record in group by

I would like assistance with adding a subquery into the below query as I understand this is the method I need to use to get the result from the last record for scan_type column, not the first record in the group by due to mysql server running 5.7.
I have tried doing this but I am not understanding how I can put the subquery into the current query. I have tried unsuccessfully which causes the query to error.
Currently I am able to get the date/time stamp by using MAX which gives me the last record for the person's attendance, but I am having trouble getting the related "scan_type". Apart from this, the remainder of the query returns all of the expected results.
Below is the current query:
SELECT A.attendance_sessions_id, A.person_id, A.scan_type, A.absence_type, MAX(A.date_time), B.name, B.student_level
FROM `attendance_record` A
LEFT JOIN `person` B ON A.person_id = B.student_no
WHERE A.scan_type IS NULL
OR A.scan_type <> 'evac_scan'
OR A.scan_type NOT LIKE 'evac_%'
GROUP BY A.attendance_sessions_id, A.person_id
Below is the current output of the above query:
attendance_sessions_id
person_id
scan_type
absence_type
MAX(A.date_time)
name
student_level
1
65
scan_in
NULL
2022-02-06 12:59:48
Chris
Year 1
Expecting scan_type = "scan_out"
attendance_record table:
attendance_record_id
attendance_sessions_id
person_id
scan_type
absence_type
date_time
4
1
65
scan_in
NULL
2022-02-05 20:13:17
5
1
65
scan_out
NULL
2022-02-05 20:14:39
6
1
65
scan_in
NULL
2022-02-06 12:06:45
7
1
65
evac_scan
NULL
2022-02-06 12:53:01
8
1
65
scan_out
NULL
2022-02-06 12:59:48
person table:
person_id
student_no
name
student_level
9
65
Chris
Year 1
attendance_sessions table:
attenance_sessions_id
session_name
session_date_time
1
February Weekend 1
2022-02-05 00:01:00
Since some time only_full_group_by is the default, (at least for MySQL 8+ ). It would be great to change this query in such a way that it's handled correctly, als in the furture.
SELECT
x.attendance_sessions_id,
x.person_id,
A.scan_type,
A.absence_type,
x.max_date_time,
B.name,
B.student_level
FROM (
SELECT
A.attendance_sessions_id,
A.person_id,
-- A.scan_type,
-- A.absence_type,
MAX(A.date_time) as max_date_time,
-- B.name,
-- B.student_level
FROM `attendance_record` A
-- LEFT JOIN `person` B ON A.person_id = B.student_no
WHERE A.scan_type IS NULL
OR A.scan_type <> 'evac_scan'
OR A.scan_type NOT LIKE 'evac_%'
GROUP BY
A.attendance_sessions_id,
A.person_id
) x
INNER JOIN `attendance_record` A ON A.attendance_sessions_id = x.attendance_sessions_id
AND A.person_id = x.person_id
AND A.date_time = x.max_date_time
LEFT JOIN `person` B ON B.student_no = A.person_id
Removed some columns (--) because of the only_full_group_by setting, and removed the LEFT JOIN because in the current sub-query the table person is no longer used.
Changed query to sub-query, and added all (remove)fields to the outer query which also includes a JOIN to get the MAX record from attendance_record
NOTE: When there are multiple records with the same date_time for one attendance_sessions_id,person_id, this query will not produce correct results.

Mysql Get Max Number of a group than make new group by that max number

I have a table, it similar with this table
ID Name Age Status
1 John 32 Life
2 Andre 99 Life
3 Anton 89 Dead
4 Maria 99 Life
5 Mario 13 Life
6 Santi 89 Dead
7 Anggy 56 Dead
8 Amir 99 Life
I want to do something like this
1. Group rows by status (Life)
2. Get the max Age from that group (99) (only the max number need)
4. Make new group by age and sort it by ID.
The result will be
8 Amir 99 Life
4 Maria 99 Life
2 Andre 99 Life
Any way to use only 1 line query for that job? with some (php) data procesing its not to hard to get the result i want, but i want to make code as clean as posible, so maybe i can do that 3 step in just a single query?
I think the right logic is:
select t.id, t.name, t.age, t.status
from table t join
(select max(t2.age) from table t2 where t2.status = 'life') m
on t.age = m.age
where t.status = 'life'
order by id desc;
select id, name, age, status
from thetable
where age =
(select max(age)
from thetable
where status="Life"
)
where status="Life"
order by id desc
Use the below mentioned query :
SELECT
*
FROM
t4
CROSS JOIN
(SELECT
MAX(`age`) AS 'age'
FROM
t4
WHERE
`status` = 'Life') AS t5
WHERE
`status` = 'Life' AND t4.`age` = t5.age
ORDER BY `id` DESC;
Check SQLFiddle

How to select distinct rows where 2 columns should match on multiple rows?

I have a table like this :
id | user_id | param_id | param_value
1 1 44 google
2 1 45 adTest
3 1 46 Campaign
4 1 47 null
5 1 48 null
6 2 44 google
7 2 45 adAnotherTest
8 2 46 Campaign2
9 2 47 null
10 2 48 null
I want to fetch all the user_ids where (param_id = 44 AND param_value=google) AND (param_id= 45 AND param_value = adTest) . So the above where clause should give only user_id = 1 and not user_id = 2 . They both have google at param_id 44 but only user 1 has param_value adTest at param_id = 45 .
The problem is the n the future more params could be added . I need to find a dynamic query . Here what i have tryed :
SELECT DISTINCT up.user_id FROM user_params AS up
LEFT JOIN user_params AS upp ON up.id = upp.id
WHERE up.param_id IN (?,?)
AND upp.param_value IN (?,?)
SELECT DISTINCT up.user_id
FROM user_params AS up
LEFT JOIN user_params AS upp ON up.id = upp.id
group by up.user_id
having sum(param_id = 44 AND param_value = 'google') >= 1
and sum(param_id = 45 AND param_value = 'adTest') >= 1
Another way:
SELECT -- DISTINCT
up1.user_id
FROM
user_params AS up1
JOIN
user_params AS up2
ON up1.user_id = up2.user_id
WHERE
up1.param_id = 44 AND up1.param_value = 'google'
AND
up2.param_id = 45 AND up2.param_value = 'adTest' ;
You do not need the DISTINCT, if there is a UNIQUE constraint on (user_id, param_id)
For efficiency, add an index on (param_id, param_value, user_id)
The problem you are dealing with is called "Relational Division" and there is a great answer by #Erwin Brandstetter here: How to filter SQL results in a has-many-through relation, with a lot of ways to write such a query, along with performance tests.
The tests were done in Postgres so some of the queries do not even run in MySQL but at least half of them do run and efficiency would be similar in many of them.
If you want to optimize this should give the same results without the need an LEFT JOIN table scans (thanks to juergen d for having part)
SELECT
user_id
FROM
user_params
WHERE
param_id IN(44, 45)
AND
param_value IN('google', 'adTest')
GROUP BY
user_id
HAVING
sum(param_id = 44 AND param_value = 'google') >= 1
AND
sum(param_id = 45 AND param_value = 'adTest') >= 1
;
see http://sqlfiddle.com/#!2/17b65/4 for demo

JOIN data from 2 MySQL tables

I have a question about joining the data from 2 tables from a MySQL Database. First I will explain what I currently have and then what I want just to be as clear as possible.
I have 2 tables in the Database which look like this:
Table: Subscriptions
Columns:
ID int(11) PK AI
Klant ID int(11)
Mail ID int(11)
Status varchar(15)
Datum varchar(15)
ID Klant_ID Mail_ID Status Datum
123 6 6 90 21-03-2013
124 6 6 10 21-03-2013
125 6 5 90 21-03-2013
126 6 5 10 21-03-2013
127 6 1 90 20-03-2013
128 6 1 10 20-03-2013
129 6 2 10 21-03-2013
130 6 2 90 21-03-2013
131 6 4 90 21-03-2013
132 6 4 10 21-03-2013
And:
Table: Mail
Columns:
ID int(11) PK AI
Content longtext
Datum varchar(15)
Titel varchar(150)
ID Content Datum Titel
1 (alot of encoded html) 18-03-13 test
2 (alot of encoded html) 18-03-13 test2
4 (alot of encoded html) 18-03-13 alles weer testen
5 (alot of encoded html) 20-03-13 testje
6 (alot of encoded html) 21-03-13 Statusupdate week 6
I am using these 2 queries to select the data from the tables now:
SELECT ID, Titel FROM Mail
SELECT * FROM Subscriptions,
(SELECT MAX(ID) as ids, Mail_ID FROM Subscriptions
WHERE Klant_ID = '".$_GET["ID"]."' GROUP BY Mail_ID) table2
WHERE ID=table2.ids
I want to get a query using JOIN to be able to create this table using html:
I personaly haven't got much experience using JOIN since I first used it yesterday, I am able to make a simple JOIN query but I just don't know how to do this. If you have more questions ask them in the comments. If anyone could help me with this it would be great!
this is a simple Join between your tables
SELECT Mail_ID, Titel, Status, Subscriptions.Datum FROM Subscriptions
JOIN Mail ON (Subscription.Mail_ID=Mail.ID)
WHERE Klant_ID = '".$_GET["ID"]."' GROUP BY Mail_ID
the order of the rows is random by a join,
if you want to get the last data, your query is right.
Try:
select mail.id, mail.titel, subscriptions.status, subscriptions.datum
from mail join subscriptions on mail.id = subscriptions.mail_id
Tyvm #kolonel peteruk, #Kaii and #JaMaBing for your answers!
With your help I was able to merge my query with yours. I finally got it to work using this query:
SELECT Mail.ID, Mail.Titel, Subscriptions.ID, Subscriptions.Status, Subscriptions.Datum, Subscriptions.Mail_ID, Subscriptions.Mail_ID, Subscriptions.Klant_ID
FROM NAW.Subscriptions
JOIN NAW.Mail
ON Mail.ID = Subscriptions.Mail_ID,
(SELECT MAX(Subscriptions.ID) as ids, Mail_ID
FROM NAW.Subscriptions
WHERE Klant_ID =6
GROUP BY Mail_ID) table2
WHERE Subscriptions.ID=table2.ids
SELECT e.ID ,e.Titel,ea.Status,ea.Datum
FROM Mail e
LEFT JOIN Subscriptions ea
ON e.ID = ea.Mail_ID
WHERE ea.Klant_ID = '".$_GET["ID"]."'
GROUP BY Mail_ID)
ORDER BY e.ID ASC

I want some logic in this query using MYSQL

I have a two tables first one is called teams and second one is called cpd and I want this result required (see result screen below). I tried myself but was not successful (see practice query below).
teams table
id name sub_cat_id
1 SACRAMENTO KINGS 19
2 KINGS 19
3 MIMAMI HEAT 19
4 HEAT 20
5 KITE 20
cpd table
id team_id status added_date
1 3 1 2012-05-26
2 3 1 2012-05-27
3 3 0 2012-05-28
practice Query
SELECT
t.`id`,t.`name`,IFNULL(cpd.status,0) AS resultStatus,IFNULL(cpd.added_date,CURDATE()) AS added_date
FROM `teams` t
LEFT JOIN cpd ON cpd.team_id = t.id
WHERE t.`sub_cat_id` = 19 OR cpd.added_date = CURDATE()
Result Screen (Required only those rows are black color in screen)
Update
Explanation ?
I am trying to get those rows who they are related with sub_cat_id = 19 like this in team table
Join team table with cpd table for cpd.status filed
cpd.status must be related with current date in cpd table like 2012-05-28
There are more than one way to get the desired result:
For example:
SELECT t.`id`,t.`name`,
IFNULL(cpd.status,0) AS resultStatus,
IFNULL(cpd.added_date,CURDATE()) AS added_date
FROM `teams` t
INNER JOIN cpd ON (cpd.team_id = t.id AND cpd.status = 0)
WHERE t.`sub_cat_id` = 19
OR
cpd.added_date = CURDATE()
Your JOIN ON cpd.team_id = t.idonly matches one tuple with the cpd table so for the other tuples date is set as NULL (because you are doing LEFT JOIN) and hence the where query gives only one tuple
SELECT
t.id,t.name,IFNULL(cpd.status,0) AS resultStatus,IFNULL(cpd.added_date,CURDATE()) AS added_date
FROM teams t
LEFT JOIN cpd ON cpd.team_id = t.id
WHERE t.sub_cat_id = 19 OR cpd.added_date = CURDATE()
GROUP BY t.id