I am trying to form a mysql query where I want to concat all the previous values until the current row -1 . For example
select * from a;
+------+
| id |
+------+
| 1 |
| 3 |
| 4 |
+------+
Desired o/p
+------+============
| id |concat_prev_to_cur
+------+============
| 1 |null
| 3 |1
| 4 |1,3
+------+============
Can this be achieved with using SELECT only
Tried this but this doesn't work
with recursive b as (select id from a union all select concat(a.id,',',b.id) from b join a on a.id=b.id) select * from b;
Update: This seems to be close to the desired output
With b as (Select id, row_number() Over(order by id) r from a) select c.id,group_concat(b.id) from b join b c on b.r < c.r group by c.r ;
+------+--------------------+
| id | group_concat(b.id) |
+------+--------------------+
| 3 | 1 |
| 4 | 1,3 |
+------+--------------------+
Maybe a recursive query is not needed.
SELECT id, (
SELECT GROUP_CONCAT(id) AS ids
FROM a AS agg
WHERE agg.id < a.id
) AS ids
FROM a
db<>fiddle
Related
I have a MYSQL table with two ID columns and one date column. I am trying to get the number of consecutive weeks based on the date column
|ID|ID2|Date |
|1 | 1 |2018-01-01|
|1 | 1 |2018-01-08|
|1 | 1 |2018-01-15|
|2 | 1 |2018-01-01|
|2 | 1 |2018-01-08|
|2 | 2 |2018-01-01|
What i am trying to achieve is a table like this
|ID |ID2|Consecutive Week|
|1 | 1 |3 |
|2 | 1 |2 |
|2 | 2 |1 |
I'm stuck with the following code:
SELECT a.ID, a.ID2 ,consec_set, COUNT(1) AS consec_count
FROM
(
SELECT IF(b.Date IS NULL, #val:=#val+1, #val) AS consec_set,a.ID2
FROM tbl a
CROSS JOIN (SELECT #val:=0) var_init
LEFT JOIN tbl b ON
a.ID = b.ID AND
a.ID2 = b.ID2 AND
YEARWEEK(a.Date ,1) = YEARWEEK(b.Date ,1) + 1
WHERE a.ID= 1
) a
GROUP BY a.consec_set;
I reached this code following several guides here but they were only with consecutive days and one ID only. Thanks in advance.
Somehow I succeeded the SQL. A bit complicated though.
SELECT id, id2, Max(cnt) FROM (
SELECT id, id2, Count(id) AS CNT FROM (
SELECT *, (
SELECT #num:=Ifnull(#num,0)) AS grouper,
#num := IF(cntn=0, #num+1, #num) AS row_number
FROM (
SELECT a.id, a.id2, a.wno, b.id IS NOT NULL AS CNTN
FROM (
SELECT DISTINCT id, id2, Week(pdate) AS WNO FROM listing) a
LEFT JOIN
(SELECT DISTINCT id, id2, Week(pdate) AS WNO FROM listing) b
ON a.wno = b.wno - 1 AND a.id = b.id AND a.id2 = b.id2
ORDER BY a.id, a.id2, a.wno
) d
) e GROUP BY e.id, e.id2, e.grouper
) f GROUP BY f.id, f.id2
Heres the fiddle with all the cases I said in the comments included:
http://sqlfiddle.com/#!9/b785df/71
Explaining from the inside out:
Selected the distinct WeekNumber, ID, ID2 values from the table
Joined the 1. table to itself again on the consecutive ones if it exists
Converted the joined rows into booleans whether the consecutive record exists or not.
Grouped the consecutive rows with indexes like 1,2,3 etc
Selected the count of the groups
Selected the maximum of the groups of which have the same ID and ID1's.
Not an answer. Too long for a comment.
Consider the following:
SELECT *, YEARWEEK(date,1) yw FROM my_table;
+-----+-----+------------+--------+
| ID1 | ID2 | Date | yw |
+-----+-----+------------+--------+
| 1 | 1 | 2018-01-01 | 201801 |
| 1 | 1 | 2018-01-08 | 201802 |
| 1 | 1 | 2018-01-15 | 201803 |
| 2 | 1 | 2018-01-01 | 201801 |
| 2 | 1 | 2018-01-07 | 201801 |
| 2 | 2 | 2018-01-01 | 201801 |
+-----+-----+------------+--------+
1,1 = 3 consecutive weeks
2,1 = 1 week
2,2 = 1 week
My records is:
name | id | AVG(point) as point
a | 1 | 6
b | 2 | 6
c | 3 | 5
d | 4 | 5
e | 5 | 4
f | 6 | 3
g | 7 | 2
How to select record below:
1.I want to select top 3 record, result follow:
name | id | AVG(point) as point
a | 1 | 6
b | 2 | 6
c | 3 | 5
d | 4 | 5
e | 5 | 4
2.I want to select record not into top 3, result follow:
name | id | AVG(point) as point
f | 6 | 3
g | 7 | 2
How can I do?
There are several ways to do these. Here's a couple using in and not in.
For the top 3, you can use in:
select *
from yourtable
where point in (select distinct point
from yourtable
order by 1 desc
limit 3)
For the rest, use not in instead:
select *
from yourtable
where point not in (select distinct point
from yourtable
order by 1 desc
limit 3)
Other methods include exists with not exists and distinct with joins.
select *
from yourtable as t1
inner join (select distinct point
from yourtable
order by 1 desc
limit 3) as t2
on t1.point = t2.point
For the second part of your question, do not use
desc
I need to find the row with maximum count. There's only one table, so it should be easy, but it isn't.
Below is the content of table:
+------+------+------+
| row1 | row2 | row3 |
+------+------+------+
| 3 | 2 | 1 |
| 6 | 4 | 5 |
| 6 | 2 | 1 |
+------+------+------+
I need to find maximum count item for row1:
Using:
SELECT COUNT(*) AS c, row1 AS name
FROM draw
GROUP BY name;
Give me the result:
+------+------+
| c | name |
+------+------+
| 1 | 3 |
| 2 | 6 |
+------+------+
But I want to display only one row with the maximum "c":
+------+------+
| c | name |
+------+------+
| 2 | 6 |
+------+------+
Using:
SELECT MAX(c), name (
SELECT COUNT(*) AS c, row1 AS name
FROM draw GROUP BY name
) AS counts;
Give me result:
+------+------+
| c | name |
+------+------+
| 2 | 3 |
+------+------+
It means that it gives maximum count (c), but give first number in name row.
Is there way to fix it?
I think this is what you want, but your requirements are a little unclear. If this was any other platform you could use windowing functions would would be better.
SELECT *
FROM (
SELECT COUNT(*) AS c, row1
FROM draw
GROUP BY row1
) as Sub1
WHERE Sub.c = (
SELECT Max(c)
FROM (
SELECT COUNT(*) AS c
FROM draw
GROUP BY row1
) as Sub2
) as Sub3
select top 1 row1, count(*)
from draw
group by row1
order by count(*) desc
Order by the count descending (i.e. highest count first) and take the first one only.
You can try this
SELECT COUNT( `row1` ) AS c, `row1`
FROM `draw`
GROUP BY `row1`
ORDER BY `row1` DESC
LIMIT 1
I've got those two tables:
Table a:
--- ID --- Name ---
Table b:
--- ID --- ID_of_a --- Date ---
Now I want to order the rows of table a by the Date (desc) of table b by the newest date.
Example:
Table a has rows with ID "1" and "2".
Table b has rows like this: {ID, ID_of_a, Date} {1, 1, "2013-06-30"}, {2, 1, "2013-07-01" }, {3, 2, "2013-07-02" }
The correct order of IDs from table a would be: 1 --- 2
Query:
SELECT DISTINCT a.ID, a.Name FROM a, b WHERE a.ID=b.ID_of_a ORDER BY b.Date desc
But this doesn't work sometimes.
Assuming there is a 1-1 relationship between the tables:
select a.*
from a left outer join
b
on a.id = b.id
order by b.date desc
If there are multiple rows in b for each a, then you need a group by:
select a.*
from a left outer join
b
on a.id = b.id
group by a.id
order by max(b.date) desc
How about
select a.name,a.id from a join (select id_of_a as id_a,max(dt) as max_dt from b group by id_of_a order by max_dt desc) e on e.id_a=a.id
Example
mysql> select * from a;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from b;
+----+---------+------------+
| id | id_of_a | dt |
+----+---------+------------+
| 1 | 1 | 2013-06-20 |
| 2 | 2 | 2013-07-01 |
| 3 | 1 | 2013-07-02 |
+----+---------+------------+
3 rows in set (0.00 sec)
mysql> select a.name,a.id from a join (select id_of_a as id_a,max(dt) as max_dt from b group by id_of_a order by max_dt desc) e on e.id_a=a.id;
+------+----+
| name | id |
+------+----+
| a | 1 |
| b | 2 |
+------+----+
2 rows in set (0.00 sec)
Basically you first select the maximum date for each id_of_a and then join it to a
I think it can be re-written to run more efficiently
$construct = "SELECT * FROM mytable GROUP BY nid HAVING nid>1";
mytable:
+----+----------+
| id | nid |
+----+----------+
| 1 | null |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
| 6 | 2 |
| 7 | 3 |
| 8 | 3 |
| 9 | 4 |
| 10 | 4 |
-----------------
How do i GROUP BY nid except nid=1? This is a brief example but with my code i am not getting the desired results. Is the query correct for what i am trying to accomplish?
How about this:
SELECT * FROM mytable WHERE nid != 1 ORDER BY nid
GROUP BY causes an aggregate query which you can only sensibly use with an aggregation function. For example, SELECT COUNT(*), nid GROUP BY nid would give you the counts of rows with a given nid.
Update: Not sure I'm understanding you, but how about this then:
(SELECT * FROM mytable WHERE nid = 1 UNION SELECT * FROM mytable WHERE nid != 1 GROUP BY nid) ORDER BY nid
I'm not sure it makes sense to mix aggregate and non-aggregate queries, though -- on the aggregate side you'll just end up with an indeterminate representative row of that group.
SELECT count(*), nid FROM mytable where nid <> 1 GROUP BY nid;
or
SELECT count(*), nid FROM mytable where nid != 1 GROUP BY nid;
Not sure if you are using Oracle or MySQL.
…
GROUP BY CASE nid WHEN 1 THEN -id ELSE nid END
…