Need a sequence number for rows in query [duplicate] - mysql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Need a sequence number for every row in MySQL query
So I found this great use:
SELECT (#row:=#row+1) AS ROW, ID
FROM TableA ,(SELECT #row := 0) r
ORDER BY ID DESC
My tables look more like this:
SELECT (#row:=#row+1) AS ROW, ID , ColA, ColB, ColC
FROM TableA
JOIN TableB on TableB.ID = TableA.ID
JOIN TableC on TableC.ID = TableA.ID
,(SELECT #row := 0) r
ORDER BY ID DESC
The #row:=#row+1 works great, but I get the row ordered by the ID.
so I get something more like this:
ROW | ID
3 15
2 10
1 2
What I am after is:
ROW | ID
1 15
2 10
3 2
Note: I noticed that if I remove the JOINs I DO get the requested result (In Which ROW is the sequential number of each row, no matter the ORDER BY of ID)
It basically seems that the row number is evaluated before the ORDER BY takes place. I need the ORDER BY to take place after row was given.
Any idea regarding how I can achieve that, and what do the JOINS do that messes it up?
Thx!

I need the ORDER BY to take place after row was given.
Then try this:
SELECT *
FROM
(
SELECT (#row:=#row+1) AS ROW, ID , ColA, ColB, ColC
FROM TableA
JOIN TableB on TableB.ID = TableA.ID
JOIN TableC on TableC.ID = TableA.ID
,(SELECT #row := 0) r
) t
ORDER BY ROW ASC

Related

How can I select from in other select in MYSQL query?

How can I select from in other select in MYSQL query?
Something like this
SET #row_number = 0;
SELECT a.num FROM
(SELECT
(#row_number:=#row_number + 1) AS num, id
FROM
main) as a where a.id=6
I want to know the number of records where id=6 if it's the first row, second row or third one
If your query has the filter where a.id = 6, then the row with id = 6 will always be the first row of the result set.
I am interpreting your question to mean: "if I sorted by id ascending, what row number is the row with id = 6 going to be on". If so, you can use a simple aggregation:
SELECT COUNT(*)
FROM main m
WHERE m.id <= 6;
Your query seems inspired by enumerating all the rows. You could do this version as well:
select m.*
from (select m.*, (#rn := #rn + 1) as rn
from main m cross join
(select #rn := 0) params
order by id
) m
where id = 6;
The first version should be more efficient, particularly with an index on id.

Alternative to UNION clause in Mysql

I have two table :- table a, table b.
table a
---ID---
1
2
3
4
5
7
table b
---ID----
2
3
4
5
6
I have to get Output Like this without UNION Command:-
----ID-----
1
2
3
4
5
6
7
Note: I have one solution with union:-
**select * from a
UNION
select * from b;**
I need alternative to this. please experts suggest.
We need another table with (at least) 2 rows for this:
CREATE TABLE d
( id INT NOT NULL
);
INSERT INTO d
(id)
VALUES
(0), (1) ;
Then, if we want to have only one query, we can use (this is for fun, DO NOT USE in production, that's why we have UNION):
SELECT DISTINCT
COALESCE(aa.id, bb.id) AS id
FROM
d
LEFT JOIN a AS aa ON d.id = 0
LEFT JOIN b AS bb ON d.id = 1
WHERE
COALESCE(aa.id, bb.id) IS NOT NULL
ORDER BY
id ;
Tested at SQLfiddle.com, and for other table combinations:
1 row - 1 row
2 rows - 2 rows
0 rows - 1 row
0 rows - 2 rows
0 rows - 0 rows
try this:
I think it works well in MS-SQL, change it to MySQL if you need, but MYSql doesnot support full outer join! Good luck
SELECT (
CASE
WHEN b.ID IS NULL
THEN a.ID
WHEN b.ID=a.ID
THEN b.ID
ELSE b.ID
END)
FROM
(SELECT ID FROM table2
)b
FULL OUTER JOIN
(SELECT ID FROM table1
) a
ON a.ID=b.ID
and play around with the query
Fiddle: http://sqlfiddle.com/#!3/c657d/13
And here is the MYSQL version:
SELECT DISTINCT COALESCE(t1.id, t2.id) id
FROM
(
SELECT TABLE_NAME <> 'table_a' n
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = SCHEMA()
AND TABLE_NAME IN('table_a', 'table_b')
) t LEFT JOIN table_a t1
ON t.n = 0 LEFT JOIN table_b t2
ON t.n = 1
Working fiddle: http://sqlfiddle.com/#!2/c657d8/34
I don't know why you are avoiding UNION but you can do like following
CREATE TABLE temp_ids(ID INT);
INSERT INTO temp_ids SELECT ID FROM a;
INSERT INTO temp_ids SELECT ID FROM b;
SELECT DISTINCT ID FROM temp_ids;
Try a full outer join and filter the NULL values.
As an abstract exercise (if this is an interview question we expect a kickback!) one ugly, innefficient solution would be to create a cartesian product and filter the unique values:
SELECT DISTINCT IF(a<>b, b.id, a.id)
FROM a, b
ORDER BY 1
;
Use FULL OUTER JOIN, like this:
SELECT CASE
WHEN t1.id IS NULL THEN t2.id
ELSE t1.id
END AS id
FROM t1
FULL OUTER JOIN t2
ON t1.id = t2.id
ORDER BY id
Note: Mysql does not support full outer joins.
Working demo: http://sqlfiddle.com/#!6/b7684/10

Mysql: How to get update rows incrementally when there are missing id's?

I have a database that all have a unique ID. They are in ascending order, and I would like to do..
update text SET name = 'hello french man' where id=1;
And change the name of every row to this data I have. So I can keep incrementing
id = id + 1;
But the problem occurs here, I've deleted some rows in the past, so there are missing IDs. For instance, there's row 1,2,3,5. Row 4 is missing because I had deleted it, so how can I update every row without skipping a name because updating row 4 won't do anything?
It is crucial that I have a 1-1 mapping with all of them and do not skip any names since order matters.
Thanks, any help is much appreciated!
You can use this solution:
UPDATE tbl a
INNER JOIN
(
SELECT id, #rn:=#rn+1 AS rn
FROM tbl
CROSS JOIN (SELECT #rn:=0) var_init
ORDER BY id
) b ON a.id = b.id
LEFT JOIN
(
SELECT id, #rn2:=#rn2+1 AS rn
FROM tbl
CROSS JOIN (SELECT #rn2:=-1) var_init
ORDER BY id
) c ON b.rn = c.rn
SET a.id = COALESCE(c.id, a.id + 1)
See the SQLFiddle Demo

Select distinct records in mysql

My table
ANONYMOUS
ONE TWO
1 2
2 1
1 2
3 1
Now i want to select distinct set of one and two.
My selected list should be
ANONYMOUS
ONE TWO
1 2
3 1
Your question isn't very clear, but I guess you mean this:
SELECT DISTINCT one, two
FROM yourtable AS T1
WHERE one <= two
OR NOT EXISTS
(
SELECT *
FROM yourtable AS T2
WHERE T1.one = T2.two
AND T1.two = T2.one
)
It finds rows with (one, two) where the reversed pair (two, one) does not exist. If both exist, it chooses the pair such that one < two. It also selects rows where the values are equal.
See it working online: sqlfiddle
If you would prefer to use a JOIN instead of NOT EXISTS you can do that:
SELECT DISTINCT T1.one, T1.two
FROM yourtable AS T1
LEFT JOIN yourtable AS T2
ON T1.one = T2.two
AND T1.two = T2.one
WHERE T1.one <= T1.two
OR T2.one IS NULL
See it working online: sqlfiddle
SELECT DISTINCT a.*
FROM `ANONYMOUS` a
LEFT JOIN `ANONYMOUS` b ON (a.one=b.two and a.two=b.one)
WHERE b.one is null or a.one<b.one
ORDER BY 1,2

Get first/last n records per group by

I have two tables : tableA (idA, titleA) and tableB (idB, idA, textB) with a one to many relationship between them. For each row in tableA, I want to retrieve the last 5 rows corresponding in tableB (ordered by idB).
I've tried
SELECT * FROM tableA INNER JOIN tableB ON tableA.idA = tableB.idA LIMIT 5
but it's just limiting the global result of INNER JOIN whereas I want to limit the result for each different tableA.id
How can I do that ?
Thanks
Much simplified and corrected Carlos solution (his solution would return first 5 rows, not last...):
SELECT tB1.idA, tB1.idB, tB1.textB
FROM tableB as tB1
JOIN tableB as tB2
ON tB1.idA = tB2.idA AND tB1.idB <= tB2.idB
GROUP BY tB1.idA, tB1.idB
HAVING COUNT(*) <= 5
In MySQL, you may use tB1.textB even if it is group by query, because you are grouping by the idB in the first table, so there is only single value of tB1.textB for each group...
I think this is what you need:
SELECT tableA.idA, tableA.titleA, temp.idB, temp.textB
FROM tableA
INNER JOIN
(
SELECT tB1.idB, tB2.idA,
(
SELECT textB
FROM tableB
WHERE tableB.idB = tB1.idB
) as textB
FROM tableB as tB1
JOIN tableB as tB2
ON tB1.idA = tB2.idA AND tB1.idB >= tB2.idB
GROUP BY tB1.idA, tB1.idB
HAVING COUNT(*) <= 5
ORDER BY idA, idB
) as temp
ON tableA.idA = temp.idA
More info about this method here:
http://www.sql-ex.ru/help/select16.php
Ensure your "B" table has an index on ( idA, idB ) for optimized order by purposes so for each "A" ID, it can quickly have the "B" order descending thus putting the newest to the top PER EACH "A" ID. Using the MySQL variables, every time the "A" ID changes, it resets the rank back to 1 for the next "A" id.
select
B.idA,
B.idB,
B.textB
#RankSeq := if( #LastAGroup = B.idA, #RankSeq +1, 1 ) ARankSeq,
#LastAGroup := B.idA as ignoreIt
from
tableB B
JOIN tableA A
on B.idA = A.idA,
(select #RankSeq := 0, #LastAGroup := 0 ) SQLVars
having
ARankSeq <= 5
order by
B.idA,
B.idB DESC
select * from tablea ta, tableb tb
where ta.ida=tb.idb and tb.idb in
(select top 5 idb from tableB order by idb asc/desc)
(asc if you want lower ids desc if you want higher ids)
less complicated and easy to include more conditions
if top clause is not present in mysql use limit clause (I don't have much knowledge abt mysql)