问题
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