问题
Having a table named books which has the following structure:
╔════════════╦═══════════╦════════╗
║ LibraryId ║ BookId ║ Price ║
╠════════════╬═══════════╬════════╣
║ 123 ║ 9001 ║ 10.99 ║
║ 123 ║ 9005 ║ 12.99 ║
║ 123 ║ 9006 ║ 7.99 ║
║ 124 ║ 8012 ║ 6.49 ║
║ 124 ║ 9001 ║ 3.19 ║
║ 124 ║ 9076 ║ 7.39 ║
╚════════════╩═══════════╩════════╝
How could I do a select that would return the full table, but additionally a field named Ordinal, that "counts" the number of books per library. The result should look something like:
╔════════════╦═══════════╦════════╦════════╗
║ LibraryId ║ BookId ║ Price ║Ordinal ║
╠════════════╬═══════════╬════════╬════════╣
║ 123 ║ 9001 ║ 10.99 ║ 1 ║
║ 123 ║ 9005 ║ 12.99 ║ 2 ║
║ 123 ║ 9006 ║ 7.99 ║ 3 ║
║ 124 ║ 8012 ║ 6.49 ║ 1 ║
║ 124 ║ 9001 ║ 3.19 ║ 2 ║
║ 124 ║ 9076 ║ 7.39 ║ 3 ║
╚════════════╩═══════════╩════════╝════════╝
I have tried something like:
SET @var_record = 1;
SELECT *, (@var_record := @var_record + 1) AS Ordinal
FROM books;
But this will continue counting irrespective of the libraryId. I need something that will reset the ordinal every time the libraryId changes. I'd prefer a single query instead of procedures.
Test data sql scripts:
create temporary table books(libraryId int, bookId int, price double(4,2));
insert into books (libraryId, bookId, price) values (123, 9001, 10.99),(123, 9005, 10.99),(123, 9006, 10.99),(124, 8001, 10.99),(124, 9001, 10.99),(124, 9076, 10.99);
回答1:
Using variables and conditions you can reset the counter based on a condition (libraryId has changed). Mandatory to order by the column libraryId.
SELECT books.*,
if( @libId = libraryId,
@var_record := @var_record + 1,
if(@var_record := 1 and @libId := libraryId, @var_record, @var_record)
) AS Ordinal
FROM books
JOIN (SELECT @var_record := 0, @libId := 0) tmp
ORDER BY libraryId;
The second if statement is used to group two assignments together and return @var_record.
if(@var_record := 1 and @libId := libraryId, @var_record, @var_record)
回答2:
perhaps you can use aggregated functions
SELECT a.LibraryId, a.BookId, a.Price,
(SELECT COUNT(b.BookId) FROM books b WHERE b.BookId = a.BookId AND b.LibraryId = a.LibraryId) AS Ordinal
FROM a.books
来源:https://stackoverflow.com/questions/19559805/mysql-select-ordinal