column_property (or other extra column) with window function?

送分小仙女□ 提交于 2020-12-15 06:27:29

问题


I have the following situation, using SQLAlchemy with a MySQL database. Assume a Person table that looks like this:

+------+-----------+----------+------------+
|  ID  | firstname | lastname | startdate  |
+------+-----------+----------+------------+
|   43 | Bob       | Smith    | 2016-12-04 |
|  873 | Mary      | Jones    | 2018-05-01 |
|  120 | Bob       | Smith    | 2020-04-02 |
|  339 | Bob       | Jones    | 2019-03-01 |
| 1022 | Bob       | Smith    | 2015-11-21 |
+------+-----------+----------+------------+

I need to generate an extra column (or any equivalent solution) having the property: For anyone having the same firstname and lastname, return a sequence number ordered by the startdate. If a person doesn't share a firstname and lastname, return NULL. The desired output is:

+------+-----------+----------+------------+------------+
|  ID  | firstname | lastname | startdate  | identifier |
+------+-----------+----------+------------+------------+
|   43 | Bob       | Smith    | 2016-12-04 | 2          |
|  873 | Mary      | Jones    | 2018-05-01 | NULL       |
|  120 | Bob       | Smith    | 2020-04-02 | 3          |
|  339 | Bob       | Jones    | 2019-03-01 | NULL       |
| 1022 | Bob       | Smith    | 2015-11-21 | 1          |
+------+-----------+----------+------------+------------+

I'd like to do this for any way of looking at the data; that is, whether I'm doing a search on all people, or just a single record, I can still see that ID 120 is #3 of all the "Bob Smith"s.

I assume that the solution involves using a window function, but I can't figure out how to use this in a column_property, or whether column_property is in fact the right way to add this to my table. This identifier would only be used for display purposes; I'd never be sorting or querying on it, so I could indeed only generate it when needed. However, it should still be part of the Person object, so that however I get there, person.identifier will be populated. And ideally this wouldn't be problematically slow, so that if I do SELECT * FROM person, I'm not firing off a zillion individual queries.


回答1:


You can use window functions. In pure SQL:

select t.*,
    case when count(*) over(partition by firstname, lastname) > 1
        then row_number() over(partition by firstname, lastname order by startdate) 
    end as identifier
from mytable t

Disclaimer: I cannot tell how to express this in SQL Alchemy.


If you need a WHERE clause, then use a subquery (otherwise, the WHERE clause applies to the window function as well):

select *
from (
    select t.*,
        case when count(*) over(partition by firstname, lastname) > 1
            then row_number() over(partition by firstname, lastname order by startdate) 
        end as identifier
    from mytable t
) t
where id = 120


来源:https://stackoverflow.com/questions/64845608/column-property-or-other-extra-column-with-window-function

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