Mysql select ordinal

泪湿孤枕 提交于 2019-12-24 10:57:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!