I have a table like this and type is innodb and id and sid are indexed.
id | sid
##########
1 | 100
1 | 101
1 | 102
1 | 103
1 | 104
1 | 105
2 | 100
2 | 101
3 | 100
3 | 101
I need id's have sid 100,...105 like id=1.
I have this query
select t1.id
from test as t1, test as t2, test as t3,
test as t4, test as t5, test as t6
where t1.sid=100
and t2.sid=101
and t3.sid=102
and t4.sid=103
and t5.sid=104
and t6.sid=105
and t1.id = t2.id = t3.id = t4.id = t5.id = t6.id
but phpmyadmin hangs when I run query.
The number of records is 2000.
What is optimized query?
It is surprising that the SQL statement shown compiles/runs.
However, you can probably rescue it by rewriting what is currently the last line to:
select t1.id
from test as t1, test as t2, test as t3,
test as t4, test as t5, test as t6
where t1.sid = 100
and t2.sid = 101
and t3.sid = 102
and t4.sid = 103
and t5.sid = 104
and t6.sid = 105
and t1.id = t2.id
and t1.id = t3.id
and t1.id = t4.id
and t1.id = t5.id
and t1.id = t6.id;
Is this query optimal?
Given your comment to Maulik Vora's answer that the range { 100 .. 105 } is just an example, then we need to know whether it is always 6 values or whether it could be 5 or 7 or some other number. However, it is likely that the optimal structure uses a temporary table (call it ListToMatch with a non-null unique column SID) containing whatever values are needed, and that the query is:
SELECT T.ID
FROM Test AS T JOIN ListToMatch AS L ON T.SID = L.SID
GROUP BY T.ID
HAVING COUNT(*) = (SELECT COUNT(*) FROM ListToMatch);
You insert the set of values you're interested in to ListToMatch; you can then get the list of ID values that match. This is likely to be more nearly optimal, not least because it adapts to 1 value and 100 values as easily as it does to 6, whereas rewriting the SQL with a 100-way self-join doesn't bear much thinking about.
select t2.id from (select id, max(sid) as mxsid, min(sid) as mnsid from test
group by id having count(id) = 6) as t2
where t2.mxsid = 105 and t2.mnsid = 100
Related
I have 3 tables:-
table1 :-
ReportType | ResourceId
t2 123
t3 5
table2:-
Id | Name | Created
1 A 10
2 B 11
123 C 12
table3:-
Id | Name | Created
4 D 13
5 E 14
6 F 15
table1's ResourceId and table2 and 3's Id column have same values
I want to create a 4th table like this:-
ReportType | ResourceId | Name | Created
t2 123 C 12
t3 5 E 14
such that wherever table1's ReportType is t2 I want the Name and Created value from table2 for the condition table1.ResourceId = table2.Id and wherever table1's ResourceType is t3 I want the Name and Created value from table3 for the condition table1.ResourceId = table3.Id.
PS: This isn't some sort of HomeWork. I have been stuck at this query for the past 1 hour, I have read various answers and tried a few queries of my own before posting the question. Any help would really be appreciated.
Explanation in comments :)
--here we join first and second table, but we filter results to include only ReportType = t2
select t1.ReportType, t1.ResourceId, t2.Name, t2.Created from table1 as t1 join table2 as t2 on t1.ResourceId = t2.id
where t1.ReportType = 't2'
union all
--here we join first and third table, but we filter results to include only ReportType = t3
select t1.ReportType, t1.ResourceId, t3.Name, t3.Created from table1 as t1 join table3 as t3 on t1.ResourceId = t3.id
where t1.ReportType = 't3'
You can use the below query:
select report_type, resourceid,name, created from dbo.t2, dbo.t1
where report_type='t2' and ResourceId=id
UNION
select report_type, resourceid,name, created from dbo.t3, dbo.t1
where report_type='t3' and ResourceId=id;
Given the following table structures:
T1:
id a
1 1
2 2
3 3
T2:
id t1_id b
1 1 1
2 1 2
3 2 3
I need to add the value of t2.b to the value of t1.a where t2.t1_id = t1.id.
A simple update with a join like the following isn't working:
UPDATE t1
JOIN t2
ON t2.t1_id = t1.id
SET t1.a = t1.a + t2.b
WHERE t2.id IN(1,2)
Expected T1 result (adds 1 and 2 to t1.a = 1; 3 to t1.a = 2):
id a
1 4
2 5
3 3
Actual T1 result (only adds 1 to t1.a = 1; 3 to t1.a = 2):
id a
1 2
2 5
3 3
At the moment I'm looking at a select that computes the full sum of values to be added using a group by, and then that result set is joined to the update... This seems like overkill for something so simple though! Does anyone have an elegant and efficient solution?
Came up with this real quickly.
UPDATE T1 AS t
JOIN (
SELECT
t1_id, SUM(b) AS sum_total
FROM
T2
WHERE
t1_id IN (1, 2)
GROUP BY
T2.t1_id
) AS t2 ON t.id = t2.t1_id
SET t.a = t.a + t2.sum_total;
I have two tables:
table1:
id
--
1
2
3
table2: (left out primary index)
id2 | cond
----------
3 | 1
3 | 0
2 | 1
2 | 1
2 | 0
I would need to construct a query that implicitly calculates this intermediary table:
temp:
id | c1 | c2
------------
1 | 0 | 2
2 | 2 | 2
3 | 1 | 2
with c1 = countRows(id2 == id && cone == 1) and c2 == countRows(id2 = 2 && cond == 1).
and then selects SELECT id FROM temp ORDER BY ABS(c1 - c2)*RAND().
My current try is kind of like:
SELECT id, COUNT(t1.id2) AS c1, COUNT(t2.id2) AS c2
FROM table1 LEFT JOIN (table2 AS t1) ON id=t1.id2 LEFT JOIN (table2 AS t2) ON t2.id2=2
WHERE t1.cond=1 AND t2.cond=1
GROUP BY t1.id2
ORDER BY ABS(c1 - c2)*RAND()
LIMIT 1
Which has multiple problems:
It doesn't select rows with no entry in table2
It doesn't correctly count
There seems to be a problem with group columns (c1, c2) in the ORDER BY part 3.
Help would be appreciated.
Update:
table1 represents players for example
table2 would be rounds played, with cond indicating a win
c1 represents the rounds won by each player
c2 represents the rounds won by a reference player (player 2 in this case)
SELECT t1.id, SUM(IFNULL(t2.cond, 0) = 1) AS c1, (SELECT SUM(cond = 1) FROM table2 WHERE id2 = 2) AS c2
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id2
GROUP BY t1.id
ORDER BY ABS(SUM(IFNULL(t2.cond, 0) = 1) - c2) * RAND();
Let's see if the first part of your query is returning valid results..
SELECT
t1.id AS id
COUNT(t2.id2) AS c1
COUNT(CASE WHEN t3.id2 = 2 THEN t3.id2 ELSE NULL END) as c2
FROM
table1 AS t1
LEFT JOIN table2 as t2
ON t1.id = t2.id2 AND t2.cond = 1
LEFT JOIN table2 as t3
ON t3.id2 = 2 AND t3.cond = 1
GROUP BY
t2.id2,
t3.id2
Can you provide schema?
How can i edit the ON operator part of my query below such that i would like the current code to work where id<=14 (which is t2.id <= t1.id as shown below) so when t1 id =14, t2 is the cumulative id from 1 to 14 (as it is now).
but for id >14 I would like the ON operator to be (t2.id=t1.id>=t1.id-2 and <=t1.id) so when t1 id=15, t2.id should be between 13 and 15. when t1 id =16, t2.id should be between 14 and 16 and so on.
I'm doing this because when i calculate col E for ids after id=14, i am only interested in getting the average of the previous 2 rows for C and D on a moving average.
My query has 2 sub queries and it updates column E. The table looks like this:
--------------------------
id | A | B | E |
--------------------------
1 | NULL | NULL |NULL|
--------------------------
2 | 4 | 6 |NULL|
--------------------------
3 | 6 | 9 |NULL|
--------------------------
This is my query where i got help from this link: Mysql Nested sub queries unknown column error
Update t join
(SELECT t1.id ,ifnull(t1.A/AVG(t2.A),0) C ,ifnull(t1.B/AVG(t2.B),0) D
FROM t t1
JOIN t t2
ON t2.id <= t1.id
group by t1.id ) AS tt
on(t.id = tt.id)
SET E = (tt.C + tt.D)/2;
Thanks,
where id<=14 (which is t2.id <= t1.id as shown below) so when t1 id =14, t2 is the cumulative id from 1 to 14 (as it is now).
Update t join
(
SELECT t1.id ,ifnull(t1.A/AVG(t2.A),0) C ,ifnull(t1.B/AVG(t2.B),0) D
FROM t t1
JOIN t t2
ON case when t2.id < 15 then t2.id <= t1.id else t2.id=t1.id>=t1.id-2 and <=t1.id end
group by t1.id
) tt on(t.id = tt.id)
SET E = (tt.C + tt.D)/2;
My table is looking as folowing:
unix_timestap ID value
1351058019 1 500
1351058029 1 505
1351058039 9 105
1351058049 9 200
1351076620 1 520
I would like be able to generate a new column contain the differences between the values per ID between the current value and the first available "past" value. With past I mean that unixtimestamp is not placed in order in the original table.
The output would be:
unix_timestap ID value difference
1351058019 1 500 0
1351058029 1 505 5
1351058039 9 105 0
1351058049 9 200 95
1351076620 1 520 15
If no previous unix_timestamp exists, the value should be zero.
A Hint/tip would be much appreciated.
Thanks
if solution still needed
select
t3.unix_timestamp, t3.id, t3.value, ifnull(t3.value - t5.value, 0) as diff
from test1 t3
join (
SELECT t1.unix_timestamp, t1.id, max(t2.unix_timestamp) as old_stamp
FROM `test1` t1
left join test1 t2 on t1.id = t2.id and t1.unix_timestamp > t2.unix_timestamp
group by t1.unix_timestamp, t1.id) as t4
on t3.unix_timestamp = t4.unix_timestamp and t3.id = t4.id
left join test1 t5 on t4.old_stamp = t5.unix_timestamp and t4.id = t5.id