Может, COUNT(DISTINCT o.id) это исправит? И 1.0 * для ratio...
Да, оба варианта верны, но числитель тоже нужно исправить. Ваши 66.7 для reno — это 4/6. Join даёт 6 строк, потому что у некоторых заказов по две строки, и COUNT(o.shipped_at) считает такие заказы дважды. Если сделать distinct только знаменатель, получится 4 отгружено / 4 заказа = неверно, только в другую сторону. Обе стороны должны считаться по уникальным заказам.
Ratio равен 0, потому что оба операнда целые, и SQLite делает целочисленное деление. 3/4 даёт 0. Если сначала умножить на 1.0, результат станет вещественным. Смотрите раздел "Operators" в https://www.sqlite.org/lang_expr.html
SELECT o.warehouse,
COUNT(DISTINCT o.id) AS orders,
COUNT(DISTINCT CASE WHEN o.shipped_at IS NOT NULL THEN o.id END) AS shipped,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN o.shipped_at IS NOT NULL THEN o.id END)
/ COUNT(DISTINCT o.id), 1) AS ship_pct,
SUM(l.qty) AS units
FROM orders o
JOIN order_lines l ON l.order_id = o.id
GROUP BY o.warehouse;
SUM(l.qty) можно оставить как есть, потому что он суммирует по строкам. Кроме того, inner JOIN отбрасывает заказы без единой строки, так что ваши 4 для reno всё равно могут отличаться от простого подсчёта. Если так, переключитесь на LEFT JOIN. Запустите и сравните с ручным подсчётом.
Переведено с английского·Показать оригинал
Maybe COUNT(DISTINCT o.id) fixes it? And 1.0 * for the ratio...
Yes, both are right, but you need to fix the numerator too. Your 66.7 for reno is 4/6. The join gives 6 rows because some orders have two lines, and COUNT(o.shipped_at) counts those orders twice. Counting only the denominator distinct would give 4 shipped / 4 orders = wrong in the other direction. Both sides have to be distinct orders.
The ratio is 0 because both operands are integers, so SQLite does integer division. 3/4 gives 0. Multiplying by 1.0 first makes it real. See the "Operators" section in https://www.sqlite.org/lang_expr.html
SELECT o.warehouse,
COUNT(DISTINCT o.id) AS orders,
COUNT(DISTINCT CASE WHEN o.shipped_at IS NOT NULL THEN o.id END) AS shipped,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN o.shipped_at IS NOT NULL THEN o.id END)
/ COUNT(DISTINCT o.id), 1) AS ship_pct,
SUM(l.qty) AS units
FROM orders o
JOIN order_lines l ON l.order_id = o.id
GROUP BY o.warehouse;
SUM(l.qty) is fine as is, because it sums over lines. Also, inner JOIN drops any order with zero lines, so your 4 for reno could still differ from a plain count. If it does, switch to LEFT JOIN. Run it and compare against your hand count.