I have got this query, which works fine:
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
ORDER BY t1.timestamp DESC
LIMIT 1000
What I would like to do is to:
1) get only those entries where the same ip occurs at least 3 times
2) group the entries by ip
So the result would look like this example:
IP TIMESTAMP
111.111.111.111 1500000000
111.111.111.111 1300000000
111.111.111.111 1100000000
222.222.222.222 1400000000
222.222.222.222 1300000000
222.222.222.222 1200000000
I have tried many approaches and I believe that this one is the closest,
but the result is 0 rows.
SELECT *, COUNT(DISTINCT ip) FROM (
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
ORDER BY t1.timestamp DESC
LIMIT 1000
) AS tmp_table
GROUP BY ip
HAVING COUNT(DISTINCT ip) > 2
Please can someone shine some light on this?
Try this:
SELECT t1.*, (SELECT DISTINCT t2.ip FROM t2 WHERE t2.id = t1.t2id)
FROM t1
WHERE
(SELECT COUNT(*)
FROM t2
WHERE t2.id = t1.t2id) >= 3
Bacause in the comments has resulted table t2 with more rows for the same IP I change my query as follow:
SELECT t1.*, t2.ip
FROM t1
JOIN t2
ON t2.id = t1.t2id
WHERE
(SELECT COUNT(*)
FROM t2 tt2
WHERE t2.ip = tt2.ip) >= 3
You can see SqlFiddle
SELECT *, COUNT(ip) FROM (
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
ORDER BY t1.timestamp DESC
LIMIT 1000
) AS tmp_table
GROUP BY ip
HAVING COUNT(ip) > 2
just remove distinct
You have to have the HAVING in the subquery
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
INNER JOIN
(
SELECT t2.ip
FROM table1 t1
INNER JOIN table1 t2 ON ( t2.id = t2.t2id )
GROUP BY t2.ip
HAVING count(ip) > 2
) t ON t2.ip = t.ip
Try like this;
SELECT t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
where t2.ip IN (SELECT ip FROM (
SELECT t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
) AS tmp_table
GROUP BY ip
HAVING COUNT(*) > 2)
ORDER BY t1.timestamp DESC
LIMIT 1000
Related
select
t1.id,
array_agg(
json_build_object('id', t2.id, 'status', t2.status)
) as statuses
from table1 t1
inner join table2 t2 on t1.id=t2.user_id
inner join table3 t3 on t1.id=t3.user_id
group by t1.id
table1
id , user
1 , 'A'
2 , 'B'
table2
user_id , status
1 , 'P'
1 , 'AP'
table3
user_id , something
1 , 'A12'
1 , 'B1212'
the table3 also one-many relationship as a result the duplication of statuses coming in the array_agg,
i tried with array_agg(distinct json_build_object()) and array_agg(distinct on json_build_object()),
how can we prevent duplications in this case ??
Just filter out the relevant status as join condition (1):
select
t1.id,
array_agg(
json_build_object('id', t2.id, 'status', t2.status)
) as statuses
from table1 t1
inner join table2 t2 on t1.id=t2.user_id
inner join table3 t3 on t1.id=t3.user_id
and t3.status = 'A12' -- 1.
group by t1.id
Furthermore, if you want to get valid JSON arrays, you should use json_agg() instead of array_agg():
select
t1.id,
json_agg(
json_build_object('id', t2.id, 'status', t2.status)
) as statuses
from table1 t1
inner join table2 t2 on t1.id=t2.user_id
inner join table3 t3 on t1.id=t3.user_id
and t3.status = 'A12'
group by t1.id
I've been tackling this for a long time and I've decided I will ask to see if someone can suggest something before my head explodes.
Here is the query I'm running, it's just repeating the same sub-sub-query multiple times within the sub-queries. I wanted to see what ALTERNATIVE options I have to speed this up.
All I can think so far is running an initial query then inserting the results for a second query.
Thanks in advance for anyones time looking at this.
SELECT t2.* FROM TABLEA as t2 where
t2.link_id in
(
select t4.LinkA as link_list from TABLEB as t4
where t4.LinkB in (
select t1.id from TABLEC as t1 where t1.number in
(
(select t2.number from TABLEC as t2 where t2.id in
(
select t3.link_id from TABLEA as t3 where t3.an like "%20278%"
)
)
)
)
union
select t4.LinkB as link_list from TABLEB as t4
where t4.LinkB in (
select t1.id from TABLEC as t1 where t1.part_number in
(
(select t2.number from TABLEC as t2 where t2.id in
(
select t3.link_id from TABLEA as t3 where t3.an like "%20278%"
)
)
)
)
union
select t4.LinkA as link_list from TABLEB as t4
where t4.LinkA in (
select t1.id from TABLEC as t1 where t1.number in
(
(select t2.number from TABLEC as t2 where t2.id in
(
select t3.link_id from TABLEA as t3 where t3.an like "%20278%"
)
)
)
)
union
select t4.LinkB as link_idlist from TABLEB as t4
where t4.LinkA in (
select t1.id from TABLEC as t1 where t1.number in
(
(select t2.number from TABLEC as t2 where t2.id in
(
select t3.link_id from TABLEA as t3 where t3.an like "%20278%"
)
)
)
)
)
I have a query:
SELECT
t1.name as Name
count ( distinct t2.key ) as Total
SUM ( IF( t2.time = '12:00' , 1 , 0) ) as QttMidDay
FROM t1
LEFT JOIN t2 on t1.key = t2.key
GROUP BY t1.key
The question is, how i do the "Conditional Count" on the 2ยบ parameter SUM for QttMidDay ?
I am guessing that you can solve your problem by aggregating before the join. My best guess is:
SELECT t1.name as Name, t2.Total, t2.QttMidDay
FROM t1 LEFT JOIN
(SELECT COUNT(DISTINCT t2.key) as Total,
SUM(t2.time = '12:00') as QttMidDay
FROM t2
GROUP BY t2.key
) t2
ON t1.key = t2.key;
I am not sure if the COUNT(DISTINCT) is necessary in the subquery.
Is is possible to store a mysql subquery somehow, if it will be used again as a subquery? Presumably this would produce cleaner code as well as save parsing overheads.
For example in the following outer join
SELECT * FROM t1
LEFT JOIN (SELECT * FROM t2 WHERE t2.foo=='bar') ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN (SELECT * FROM t2 WHERE t2.foo=='bar') ON t1.id = t2.id
It would be nice not to repeat (SELECT * FROM t2 WHERE t2.foo=='bar').
No, you can't. If MySQL had CTE (Common Table Expressions), you could use this:
WITH tmp AS
(SELECT * FROM t2 WHERE t2.foo = 'bar')
SELECT * FROM t1
LEFT JOIN tmp ON t1.id = tmp.id
UNION
SELECT * FROM t1
RIGHT JOIN tmp ON t1.id = tmp.id
If MySQL had FULL JOIN (which alas, it hasn't either!), you could use this:
SELECT * FROM t1
FULL JOIN (SELECT * FROM t2 WHERE t2.foo = 'bar') tmp
ON t1.id = tmp.id
Of course do it like this
SET #condition := (SELECT * FROM t2 WHERE t2.foo=='bar');
SELECT * FROM t1
LEFT JOIN (#condition) ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN (#condition) ON t1.id = t2.id
Query 1:
SELECT if(COUNT(0),1,0) as 'IsPresent'
FROM table1
WHERE Id=1500;
Query2:
If IsPresent is 1, then
select t2.mark,t2.age from table2 t2,table1 t1
where t1.ID=t2.ID order by t1.ID;
If IsPresent is 0, then
select mark,age from table2;
ie. if entry is present in a table, i need to join else i don't need to join.
Is there any way we can achieve this with a single mysql select query?
I think you can union the two different query cases which would look like:
SELECT T2.MARK, T2.AGE
FROM TABLE1 T1, TABLE2 T2
WHERE
T1.ID=T2.ID AND
T1.ID=1500
UNION
SELECT MARK, AGE
FROM TABLE1
WHERE
NOT ID=1500
SELECT t2.mark, t2.age
FROM table2 t2
JOIN table1 t1
ON t1.id = t2.id
WHERE EXISTS
( SELECT *
FROM table1
WHERE id=1500
)
UNION ALL
SELECT t2.mark, t2.age
FROM table2 t2
WHERE NOT EXISTS
( SELECT *
FROM table1
WHERE id=1500
)
which can be simplified to:
SELECT t2.mark, t2.age
FROM table2 t2
LEFT JOIN table1 t1
ON t1.id = t2.id
AND EXISTS
( SELECT *
FROM table1
WHERE id=1500
)