我准备的SQL查询如下:
SELECT
r.BookingID, r.FlightDate, r.CarrierCode, r.FlightNo,
r.InvoiceNumber, SUM(r.Price) total_price
FROM
Reservations r
INNER JOIN
(SELECT r.BookingID, COUNT(*) cnt
FROM Reservations r
GROUP BY r.BookingID) AS all_group ON r.BookingID = all_group.BookingID
LEFT JOIN
(SELECT r.BookingID, COUNT(*) cnt
FROM Reservations r
WHERE r.InvoiceNumber IS NOT NULL
GROUP BY r.BookingID) AS not_null_group ON r.BookingID = not_null_group.BookingID
WHERE
all_group.cnt = not_null_group.cnt
OR r.InvoiceNumber IS NULL
GROUP BY
r.BookingID, r.FlightDate, r.CarrierCode, r.FlightNo, r.InvoiceNumber
ORDER BY
r.FlightDate, r.CarrierCode, r.FlightNo, r.InvoiceNumber
我想转换为 LINQ,但它对我来说太复杂了。你能指导我吗?
非常感谢...
现有查询的精确翻译将产生以下 LINQ:
from r in Reservations
join all_group in
(from r in Reservations r
group by r.BookingID into g
select new { BookingID: g.Key, cnt = g.Count() })
on r.BookingID = all_group.BookingID
join not_null_group_joined in
(from Reservations r
where r.InvoiceNumber != null
group by r.BookingID into g
select new { BookingID = g.Key, cnt = g.Count() })
on r.BookingID = not_null_group_joined.BookingID into gj1
from not_null_group_joined in gj1.DefaultIfEmpty()
where
all_group.cnt = not_null_group.cnt
|| r.InvoiceNumber == null
group by
new { r.BookingID, r.FlightDate, r.CarrierCode, r.FlightNo, r.InvoiceNumber }
into g
select
new { g.Key.BookingID, g.Key.FlightDate, g.Key.CarrierCode, g.Key.FlightNo, g.Key.InvoiceNumber,
total_price: g.Sum(r => r.Price)
}
order by
new { g.Key.FlightDate, g.Key.CarrierCode, g.Key.FlightNo, g.Key.InvoiceNumber };
但是,这无论如何都不是很有效。首先,可以使用条件聚合和
HAVING
组合两个子查询
COUNT(*) cnt_all_group, COUNT(InvoiceNumber) cnt_not_null
更好的是,使用窗口函数消除所有这些。
SELECT
r.BookingID,
r.FlightDate,
r.CarrierCode,
r.FlightNo,
r.InvoiceNumber,
CASE WHEN SUM(COUNT(*)) OVER (PARTITION BY r.BookingID)
= SUM(COUNT(InvoiceNumber)) OVER (PARTITION BY r.BookingID)
THEN SUM(r.price)
ELSE SUM(CASE WHEN r.InvoiceNumber IS NULL THEN r.price END)
END AS total_price
FROM Reservations r
GROUP BY
r.BookingID,
r.FlightDate,
r.CarrierCode,
r.FlightNo,
r.InvoiceNumber
ORDER BY
r.FlightDate,
r.CarrierCode,
r.FlightNo,
r.InvoiceNumber;
等效的 LINQ 要让它使用窗口函数有点复杂,但类似这样的东西应该可以工作:
from r in Reservations
group by new {
r.BookingID,
r.FlightDate,
r.CarrierCode,
r.FlightNo,
r.InvoiceNumber
} into g1
select new {
g1.BookingID,
g1.FlightDate,
g1.CarrierCode,
g1.FlightNo,
g1.InvoiceNumber,
total_price = g1.Sum(r => r.Price),
null_price = g1.Sum(r => r.InvoiceNumber == null ? r.Price : null),
all_count = g1.Count(),
not_null = g1.Count(r => r.InvoiceNumber != null)
}
group by g1.BookingId into g2
from r2 in g2
select new {
r2.BookingID,
r2.FlightDate,
r2.CarrierCode,
r2.FlightNo,
r2.InvoiceNumber,
total_price = g2.Sum(all_count) == g2.Sum(not_null)
? r2.total_price
: r2.null_price
};