如何在 PostgreSQL 中获取不同城市的最新日期

问题描述 投票:0回答:3

我目前正在尝试在 PostgreSQL 上执行一项任务,我需要准备一份城市列表及其上次预订日期,其中还必须包括酒店 ID 和照片。

这是迄今为止我的 SQL 查询:

SELECT city.name, booking.booking_date as last_booking_date, hotel.id as hotel_id, hotel.photos ->> 0 as hotel_photo
FROM city 
INNER JOIN hotel
    ON city.id = hotel.city_id 
INNER JOIN booking 
    ON booking.hotel_id = hotel.id
WHERE 
    booking.booking_date = (SELECT MAX(booking_date) FROM booking WHERE hotel_id = hotel.id)
ORDER BY city.name ASC;

现在它的作用是返回城市(按字母顺序排序,并且可以重复),其中还包含其预订日期(也从最早到最晚排序)。如果很多酒店的预订量都一样,那我就得按ID排序了

感谢下面的答案,并进行一些细微的调整,我能够按字母顺序返回不同的城市,但不能按某些城市的最新日期返回。

SELECT distinct on (city.name) 
  city.name, 
  booking.booking_date as last_booking_date, 
  hotel.id as hotel_id, 
  hotel.photos ->> 0 as hotel_photo
FROM city 
INNER JOIN hotel
    ON city.id = hotel.city_id 
INNER JOIN booking 
    ON booking.hotel_id = hotel.id
WHERE 
    booking.booking_date = (SELECT MAX(booking_date) 
                            FROM booking
                            WHERE hotel_id = hotel.id)
    AND 
    booking.id = (SELECT MAX(id) FROM booking WHERE hotel_id = hotel.id)
ORDER BY city.name, hotel.id ASC, booking.booking_date ASC;

结果如下,也显示了预期的结果。

如您所见,有些城市并未按最晚预订日期排序。我尝试过上面 SQL 查询的变体,例如:

SELECT distinct on (city.name) 
  city.name, 
  booking.booking_date as last_booking_date, 
  hotel.id as hotel_id, 
  hotel.photos ->> 0 as hotel_photo
FROM city 
INNER JOIN hotel
    ON city.id = hotel.city_id 
INNER JOIN booking 
    ON booking.hotel_id = hotel.id
WHERE 
    booking.booking_date = (SELECT MAX(booking_date) 
                            FROM booking
                            WHERE hotel_id = hotel.id)
    AND 
    booking.hotel_id = (SELECT MAX(hotel_id) FROM booking WHERE hotel_id = hotel.id)
ORDER BY city.name, hotel.id ASC, booking.booking_date ASC;

SELECT distinct on (city.name) 
  city.name, 
  booking.booking_date as last_booking_date, 
  hotel.id as hotel_id, 
  hotel.photos ->> 0 as hotel_photo
FROM city 
INNER JOIN hotel
    ON city.id = hotel.city_id 
INNER JOIN booking 
    ON booking.hotel_id = hotel.id
WHERE 
    booking.booking_date = (SELECT MAX(booking_date) 
                            FROM booking
                            WHERE hotel_id = hotel.id)
    AND 
    booking.id = (SELECT MAX(id) FROM booking WHERE hotel_id = hotel.id)
    AND 
    booking.hotel_id = (SELECT MAX(hotel_id) FROM booking WHERE hotel_id = hotel.id)
ORDER BY city.name, hotel.id ASC, booking.booking_date ASC;

但它们都显示与之前相同的结果。

这样,我如何获取最新日期的行?对于上下文,这是第一个查询返回的内容。

sql database postgresql
3个回答
1
投票

使用

DISTINCT ON
。它将根据
ORDER BY
子句中的顺序选择子集的第一个元素。例如:

SELECT distinct on (city.name) -- changed here
  city.name, 
  booking.booking_date as last_booking_date, 
  hotel.id as hotel_id, 
  hotel.photos ->> 0 as hotel_photo
FROM city 
INNER JOIN hotel
    ON city.id = hotel.city_id 
INNER JOIN booking 
    ON booking.hotel_id = hotel.id
WHERE 
    booking.booking_date = (SELECT MAX(booking_date) 
                            FROM booking
                            WHERE hotel_id = hotel.id)
ORDER BY city.name, booking.booking_date DESC; -- changed here

0
投票

我相信,您不需要 WHEN 子查询。 您的 ORDER BY 语句略有偏差:它首先按城市排序,然后按酒店排序,然后才选择日期。 因此,如果您将 ORDER BY 修改为按 city.name、date DESC 和 hotel_id,则应该可以正常工作。
找到下面的代码:

SELECT distinct on (city.name) 
  city.name, 
  booking.booking_date as last_booking_date, 
  hotel.id as hotel_id, 
  hotel.photos ->> 0 as hotel_photo
FROM city 
INNER JOIN hotel
    ON city.id = hotel.city_id 
INNER JOIN booking 
    ON booking.hotel_id = hotel.id
ORDER BY city.name, booking.booking_date DESC, hotel.id ASC;

0
投票

前几天我看到了类似的问题,就像这样

Write a query to retrieve the city name, the date of the most recent reservation in that city, the hotel ID of the most popular hotel (the one with the highest number of bookings), and a photo of that hotel for each city. The results should be sorted in ascending order by the city name. If two hotels have the same number of bookings, they should be sorted in ascending order by hotel ID.

我正在使用 MySql,但除了照片字段之外,整个查询应该是相同的。

with bookingCount as (
    select
        h.id hotel_id,
        h.city_id,
        -- hotel_photo
        count(b.id) b_count
    from hotel h
    join booking b
    on h.id = b.hotel_id 
    group by h.id
)
select
    sb1.name city_name,
    sb1.last_booking_date,
    sb2.hotel_id
    -- hotel_photo
from 
(
    select 
        c.id city_id,
        c.name ,
        max(b.booking_date) last_booking_date
    from city c
    join hotel h
    on h.city_id = c.id
    join booking b 
    on b.hotel_id = h.id 
    group by c.id
) sb1 
join 
(
    select 
        bc1.city_id,
        min(bc1.hotel_id) hotel_id
        -- hotel_photo
    from 
    bookingCount bc1
    where bc1.b_count = (
        SELECT MAX(b_count)
        FROM BookingCount bc2
        WHERE bc1.city_id = bc2.city_id
    )
    group by bc1.city_id
) sb2 
on sb2.city_id = sb1.city_id
order by 
    city_name, 
    hotel_id
;
© www.soinside.com 2019 - 2024. All rights reserved.