【问题标题】:RANK() Function on DATE IN SQLSQL 中 DATE 上的 RANK() 函数
【发布时间】:2020-04-03 19:33:20
【问题描述】:

我为此使用 PopSQL。

请考虑以下几点:我正在尝试使用 PayDate 对每个国家/地区进行排名。对于每个 PayDate,关联的国家/地区不止一个。我的愿望是用特定的 PayDate 或其计数对每个国家/地区进行分组,并相应地对它们进行排名。

CREATE TABLE Country
(
    CountryID INT PRIMARY KEY,
    CountryName VARCHAR(40)
);

CREATE TABLE State
(
    StateID INT PRIMARY KEY,
    StateName VARCHAR(40),
    CountryID INT,
    FOREIGN KEY(CountryID) REFERENCES Country(CountryID)
);

CREATE TABLE City
(
    CityID INT PRIMARY KEY,
    CityName VARCHAR(40),
    StateID INT,
    FOREIGN KEY(StateID) REFERENCES State(StateID)
);

CREATE TABLE Rooms 
(
    RoomID INT PRIMARY KEY,
    RoomTypeID INT,
    RoomBandID INT,
    RoomFacilityID INT,
    CityID INT,
    Floor INT,
    AddionalNotes VARCHAR(255),
    FOREIGN KEY(RoomTypeID) REFERENCES RoomType(RoomTypeID),
    FOREIGN KEY(RoomBandID) REFERENCES RoomBand(RoomBandID),
    FOREIGN KEY(RoomFacilityID) REFERENCES RoomFacility(RoomFacilityID),
    FOREIGN KEY(CityID) REFERENCES City(CityID)
);

CREATE TABLE DT_Date
(
    DateID INT NOT NULL,
    FullDate Datetime NOT NULL, 
    DateMonth INT NOT NULL, 
    Quarter INT NOT NULL,
    DateYear year NOT NULL, 
    PRIMARY KEY(DateID)
);

CREATE TABLE Customer
(
    CustomerID INT PRIMARY KEY,
    CustomerForename VARCHAR(20),
    CustomerSurname VARCHAR(20),
    CustomerDOB DATetime,
    CustomerHomePhone INT,
    CustomerMobilePhone INT,
    CustomerWorkPhone INT,
    CustomerEmail VARCHAR(40),
    CityID INT,
    FOREIGN KEY (CityID) REFERENCES City(CityID)

);

CREATE TABLE Payments
(
    PaymentID INT PRIMARY KEY, 
    PaymentComment VARCHAR(255), 
    PaymentsMethodID INT, 
    PayDate Datetime,
    RoomID INT,
    DateID INT,
    CustomerID INT,
    Price INT,
    PaymentAmount INT,
    FOREIGN KEY(RoomID) REFERENCES Rooms(RoomID),
    FOREIGN KEY(PaymentsMethodID) REFERENCES PaymentsMethod(PaymentsMethodID),
    FOREIGN KEY(DateID) REFERENCES DT_Date(DateID),
    FOREIGN KEY(CustomerID) REFERENCES Customer(CustomerID)
);

也请看看我的最后一次尝试:

select 
    rank() over (PARTITION BY CountryName order by count(PayDate)),
    CountryName, PayDate, count(Paydate)
from 
    City, Payments, Rooms, Customer, State, Country, DT_Date
where
    Payments.PayDate >= "2010-00-00 00:00:00" 
    and Payments.CustomerID = Customer.CustomerID
    and State.CountryID = Country.CountryID
    and City.StateID = State.StateID
    and Customer.CityID = City.CityID
    and Payments.DateID = DT_Date.DateID
group by 
    CountryName, PayDate;

查询成功。但是,结果不正确,因为英国有两个 PayDate,美国有一个 PayDate。以下是显示的结果:

Rank CountryName         PayDate       count(Paydate)
1       UK        2015-12-31 00:00:00    4
1       UK        2014-06-10 00:00:00    4
1       USA       2011-11-25 00:00:00    4

预期输出:

Rank CountryName        
1       UK        

2       USA       

【问题讨论】:

  • 从不FROM 子句中使用逗号。 始终正确、明确、标准、可读JOIN语法。
  • @GordonLinoff 到目前为止还没有遇到任何性能问题,但感谢您的提示。请问隐式和显式有什么区别?另外,这和我问的问题有什么关系?
  • 如果最终结果中不需要PayDatecount(Paydate),为什么还要在查询中使用它们?你的“预期结果”真的是你所期待的吗?
  • @django-unchained 不,预期的结果是 Rank 和 CountryName。我在查询中显示了 PayDate 和 Count(PayDate) 以显示有 3 个 PayDate,即英国有 2 个,美国有 1 个,基于这些我想查看排名。谢谢!

标签: sql data-warehouse olap popsql


【解决方案1】:

不要按 PayDate 分组,只能按 CountryName 分组。这意味着您不能在结果中包含 PayDate,但无论如何您都不想这样做。

同时从您的分区中删除 CountryName。您的排名仅按 PayDate 计数排序。

要让最大的计数排在第一位,请使用降序。

select
  rank() over (order by count(PayDate) desc ) as "rank",
  CountryName
from City , Payments,Rooms,Customer,State,Country,DT_Date
WHERE Payments.PayDate >= '2010-00-00 00:00:00'
ANd Payments.CustomerID = Customer.CustomerID
And State.CountryID = Country.CountryID
AND City.StateID = State.StateID
And Customer.CityID = City.CityID
and Payments.DateID = DT_Date.DateID
GROUP by CountryName

Here's a simplified demo.

一些旁注。

虽然它可能适用于您的 SQL 实现,但 2010-00-00 00:00:00 是一个狡猾的日期时间。使用2010-01-01 00:00:00 或更好的数据库相当于year(Payments.PayDate) >= 2010

不要按 CountryName 分组,按 Country.CountryId 分组。按名称分组会导致意外地将两个事物分组在一起,并且架构中不强制执行唯一的国家/地区名称(它们应该是)。

最后,显式连接确实更容易理解和维护查询。

【讨论】:

  • select rank() over (PARTITION BY CountryName order by count(PayDate) ) as "rank", Country.CountryID from City , Payments,Rooms,Customer,State,Country,DT_Date WHERE Year (Payments.PayDate) >= 2010 ANd Payments.CustomerID = Customer.CustomerID And State.CountryID = Country.CountryID AND City.StateID = State.StateID And Customer.CityID = City.CityID and Payments.DateID = DT_Date.DateID GROUP by CountryID; 我按照您的建议修复了它。它有效,但结果显示两个 CountryID 的排名为 1,而它必须显示不同的排名。非常感谢!你的最后一条评论让我很开心!
  • @ShariqShah 我的错。同时删除partition by CountryName,并使用降序排列。
猜你喜欢
  • 1970-01-01
  • 2017-07-25
  • 1970-01-01
  • 2018-04-12
  • 2023-04-04
  • 2016-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多