I have this table, and I want to select all distinct user_id values where there is both an event='AAAAAAAAAA' and event ='XXXXXXXXXX' (i.e. only result should be user_id=123456789)
unique_row_id user_id event event_timestamp
----------------------------------------------------------------
0 123456789 AAAAAAAAAA 2010-01-20 15:00:00
1 123456789 abcdefghij 2010-01-20 15:00:05
2 123456789 XXXXXXXXXX 2010-01-20 15:00:15
3 987654321 AAAAAAAAAA 2010-01-20 16:00:00
4 987654321 abcdefghij 2010-01-20 16:00:05
5 987654321 abcdefghij 2010-01-20 16:00:15
6 111111111 XXXXXXXXXX 2010-01-20 16:01:00
7 111111111 XXXXXXXXXX 2010-01-20 16:01:05
8 111111111 XXXXXXXXXX 2010-01-20 16:01:15
I've tried both:
SELECT distinct user_id from mydata where event='AAAAAAAAAA' and event='XXXXXXXXXX'
which gives me an empty result set, and
SELECT distinct user_id from mydata where event='AAAAAAAAAA' or event='XXXXXXXXXX'
which gives me everything. Any suggestions - I'm guessing I need to go down the 'join' road here do I?
Try this:
select user_id from mydata where event='AAAAAAAAAAA'
union
select user_id from mydata where event='XXXXXXXXXXX';
This will select both lists (users w/ AAA, users w/ XXX), and then merge them together, removing duplicate rows.
Hope that helps!
Thanks,
Joe
I'd do it with a subquery:
select distinct user_id
from mydata m
where event = 'AAAAAAAAAA'
and exists (
select 1
from mydata
where user_id = m.user_id
and event = 'XXXXXXXXXX'
);
The conditions on the WHERE clause are only applicable on a single row at a time.
In order to check two rows, you have to use JOIN:
SELECT distinct a.user_id
FROM mydata a, mydata b
WHERE a.event='AAAAAAAAAA' AND b.event='XXXXXXXXXX' AND a.user_id = b.user_id
If you know that an event can only appear once per user, you can use GROUP BY:
SELECT user_id
FROM mydata
WHERE event in ('AAAAAAAAAA', 'XXXXXXXXXX')
GROUP BY user_id
HAVING count(user_id)=2
SELECT
DISTINCT user_id
FROM
my_table AS outer_table
WHERE
EXISTS (
SELECT
1
FROM
my_table AS inner_table_A
WHERE
inner_table_A.user_id = outer_table.user_id AND
inner_table_A.event = 'AAAAAAAAAA'
) AND
EXISTS (
SELECT
1
FROM
my_table AS inner_table_B
WHERE
inner_table_B.user_id = outer_table.user_id AND
inner_table_B.event = 'XXXXXXXXXX'
)
I would use something like this...
SET #events := 'AAAAAAAAAA,XXXXXXXXXX';
SELECT user_id
FROM mydata
GROUP BY user_id
HAVING GROUP_CONCAT(DISTINCT event ORDER BY event SEPARATOR ',') = #events;
Related
Let's say I have table like this:
some_id
date
1
2022-02-01
2
2022-02-02
3
2022-02-03
3
2022-02-04
3
2022-02-05
3
2022-02-06
I want to get the number of rows based on the id where the date was found?
I tried this but it's not working:
SELECT COUNT(id) FROM dates WHERE date = '2022-02-04'
Expected output should be 4 rows since there are 4 same id's where the 2022-02-04 was found.
This should do the job:
SELECT COUNT(*) FROM tbl
WHERE id IN (
SELECT id FROM tbl WHERE `date`='2022-02-04'
)
An exists query should do it:
SELECT id, COUNT(*)
FROM t
WHERE EXISTS (
SELECT 1
FROM t AS x
WHERE x.id = t.id
AND x.date = '2022-02-04'
)
GROUP BY id
Using exists logic we can try:
SELECT COUNT(*)
FROM dates d1
WHERE EXISTS (SELECT 1 FROM dates d2
WHERE d2.some_id = d1.some_id AND
d2.date = '2022-02-04');
Hi I'm trying to write a correct query for MySQL to retrieve values from 4 columns (from, to, content, date or all if that's easier) based on 2 columns being unique in the same table. The idea is to retrieve a list of only last messages sent and received by a user X
TABLE
msg_id|msg_from|msg_to|msg_new|msg_content|date
1 user1 sw1 1 message1 2014-02-06
2 user1 sw1 1 message2 2014-02-06
3 user1 sw3 0 message3 2014-02-06
4 user1 sw5 0 message4 2014-02-06
5 sw2 sm2 1 message5 0000-00-00
6 sw2 sm4 1 message6 2014-02-20
7 sw1 user1 1 message7 2014-02-20
8 user1 sw5 1 message8 2014-02-20
My last attempt :
SELECT t1.* FROM (SELECT MAX(msg_id) AS nr, msg_from, msg_to
FROM com_msg GROUP BY msg_from) AS t2
INNER JOIN com_msg t1 ON t1.msg_from=t2.msg_from AND t1.msg_id=t2.nr
WHERE t1.msg_to='sw1' OR t1.msg_from='sw1'
which returns :
2| user1|sw1 |1|message2|2014-02-06
7| sw1 |user1|1|message7|2014-02-20
but should only return :
7| sw1 |user1|1|message7|2014-02-20
If I understant your question correctly, this query should return what you need:
SELECT com_msg.*
FROM com_msg INNER JOIN (SELECT MAX(msg_id) max_id
FROM com_msg
WHERE 'sw1' IN (msg_from, msg_to)
GROUP BY
CASE WHEN msg_from!='sw1' THEN msg_from
ELSE msg_to END) m
ON com_msg.msg_id = m.max_id
IDs needs to be ordered, otherwise you should use MAX(date)
Please see fiddle here.
Basically, you need to wrap this with another query, because your where clause is showing you records where either the to or the from equal the user. I'm not a MySQL guru, but you should be able to do something like this:
select top 1 *
FROM (
SELECT t1.* FROM (
SELECT MAX(msg_id) AS nr, msg_from, msg_to
FROM com_msg
GROUP BY msg_from
) AS t2
INNER JOIN com_msg t1 ON t1.msg_from=t2.msg_from AND t1.msg_id=t2.nr
WHERE t1.msg_to='sw1' OR t1.msg_from='sw1'
)
ORDER BY date DESC
This will return the most recent entry from your results based on the date.
If you are looking for just a single record returned of the last email like your example shows, this should do it...
Select TOP 1 msg_from, msg_to, msg_content, date
From com_msg
Where msg_from='sw1' OR msg_to='sw1'
ORDER BY msg_id DESC
I have a query that returns data in the following format:
id | name | number
1 John 12545
1 John 50496
2 Mary 23443
3 Mark 54
3 Mark 5600
3 Mark 50206
I would like to find out the number of distinct ids that appear in the result set. For example, for the result above. I would like to obtain the value 3.
Is there any way to add a column so the result looks like this instead?
count | id | name | number
3 1 John 12545
3 1 John 50496
3 2 Mary 23443
3 3 Mark 54
3 3 Mark 5600
3 3 Mark 50206
My query is:
SELECT * FROM (
SELECT id FROM tableA
WHERE xyz
) as t1
JOIN tableB using (id)
SELECT (SELECT COUNT(DISTINCT id) FROM tableName) totalCount,
id,name,number
FROM tableName
or by using CROSS JOIN
SELECT x.totalCount,
a.id, a.name, a.number
FROM tableName a, (SELECT COUNT(DISTINCT id) totalCount
FROM tableName) x
You should try :
SELECT id,name,number, (SELECT COUNT(DISTINCT name) FROM YourTableName) FROM YourTableName
Good luck
SELECT COUNT(DISTINCT id) would be faster than using column name.
SELECT (SELECT COUNT(DISTINCT id) FROM tableName) as 'count',
id,name,number
FROM tableName
SELECT COUNT(id) AS count , id, name, number
FROM
(
SELECT id
FROM tableA
WHERE xyz
) as t1
JOIN tableB using (id)
GROUP BY id, name, number
I want to count how many times each user has rows within '5' of eachother.
For example, Don - 501 and Don - 504 should be counted, while Don - 501 and Don - 1600 should not be counted.
Start:
Name value
_________ ______________
Don 1235
Don 6012
Don 6014
Don 6300
James 9000
James 9502
James 9600
Sarah 1110
Sarah 1111
Sarah 1112
Sarah 1500
Becca 0500
Becca 0508
Becca 0709
Finish:
Name difference_5
__________ _____________
Don 1
James 0
Sarah 2
Becca 0
Use the ABS() function, in conjunction with a self-join in a subquery:
So, something like:
SELECT name, COUNT(*) / 2 AS difference_5
FROM (
SELECT a.name name, ABS(a.value - b.value)
FROM tbl a JOIN tbl b USING(name)
WHERE ABS(a.value - b.value) BETWEEN 1 AND 5
) AS t GROUP BY name
edited as per Andreas' comment.
Assuming that each name -> value pair is unique, this will get you the count of times the value is within 5 per name:
SELECT a.name,
COUNT(b.name) / 2 AS difference_5
FROM tbl a
LEFT JOIN tbl b ON a.name = b.name AND
a.value <> b.value AND
ABS(a.value - b.value) <= 5
GROUP BY a.name
As you'll notice, we also have to exclude the pairs that are equal to themselves.
But if you wanted to count the number of times each name's values came within 5 of any value in the table, you can use:
SELECT a.name,
COUNT(b.name) / 2 AS difference_5
FROM tbl a
LEFT JOIN tbl b ON NOT (a.name = b.name AND a.value = b.value) AND
ABS(a.value - b.value) <= 5
GROUP BY a.name
See the SQLFiddle Demo for both solutions.
Because the OP also wants de zero counts, we'll need a self- left join. Extra logic is needed if one person has two exactly the same values, these should also be counted only once.
WITH cnts AS (
WITH pair AS (
SELECT t1.zname,t1.zvalue
FROM ztable t1
JOIN ztable t2
ON t1.zname = t2.zname
WHERE ( t1.zvalue < t2.zvalue
AND t1.zvalue >= t2.zvalue - 5 )
OR (t1.zvalue = t2.zvalue AND t1.ctid < t2.ctid)
)
SELECT DISTINCT zname
, COUNT(*) AS znumber
FROM pair
GROUP BY zname
)
, names AS (
SELECT distinct zname AS zname
FROM ztable
GROUP BY zname
)
SELECT n.zname
, COALESCE(c.znumber,0) AS znumber
FROM names n
LEFT JOIN cnts c ON n.zname = c.zname
;
RESULT:
DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 14
zname | znumber
-------+---------
Sarah | 3
Don | 1
Becca | 0
James | 0
(4 rows)
NOTE: sorry for the CTE, I had not seen th mysql tag,I just liked the problem ;-)
SELECT
A.Name,
SUM(CASE WHEN (A.Value < B.Value) AND (A.Value >= B.Value - 5) THEN 1 ELSE 0 END) Difference_5
FROM
tbl A INNER JOIN
tbl B USING(Name)
GROUP BY
A.Name
Can not understand how to make an select:
table structure:
id name value date
1 ivan 2 2010-01-01
2 ivan 3 2010-05-08
3 ivan 1 2009-04-14
4 sasha 2 2011-11-11
5 sasha 9 2012-04-04
How to get?:
name value(in last time)
ivan 3
sasha 9
This is untested, but should work:
SELECT
name,
MAX(value)
FROM
structure
GROUP BY
name
This query should work
select f.name, f.value, f.date
from (
select id,name,max(date) as dat from tableName group by name
) as x inner join tableName as f on f.name = x.name and f.date = x.dat;
SELECT DISTINCT name, value FROM table ORDER BY date DESC
thats what i understand from your current description so far.
Something like this:
SELECT
MAX(value),
name
FROM
Table
GROUP BY
name