我有两张桌子。一个表按月显示入库库存,另一个表按月显示出库存。基本上我想在一个表上按月显示入站和出站库存。
1
select
warehouses.id,
count(pallets.id),
to_char(pallets.in_date, 'FMMonth-YY') as in_month
from pallets
inner join reservations
on pallets.reservation_id = reservations.id
inner join warehouses
on reservations.warehouse_id = warehouses.id
where pallets.in_date is not null
group by
warehouses.id,
date_part('month', pallets.in_date),
date_part('year', pallets.in_date),
to_char(pallets.in_date, 'FMMonth-YY')
order by
date_part('year', pallets.in_date),
date_part('month', pallets.in_date)
和2.
select
warehouses.id as id,
count(pallets.id),
to_char(pallets.out_date, 'FMMonth-YY') as out_month
from pallets
inner join reservations
on pallets.reservation_id = reservations.id
inner join warehouses
on reservations.warehouse_id = warehouses.id
where pallets.in_date is not null and pallets.out_date is not null
group by
date_part('month', pallets.out_date),
date_part('year', pallets.out_date),
to_char(pallets.out_date, 'FMMonth-YY'),
warehouses.id
order by
date_part('year', pallets.out_date),
date_part('month', pallets.out_date)
我尝试使用子查询加入第二个表,但返回的值都是各种各样的。
select
warehouses.id,
count(pallets.id),
count(out.out),
to_char(pallets.in_date, 'FMMonth-YY') as in_month
from pallets
inner join reservations
on pallets.reservation_id = reservations.id
inner join warehouses
on reservations.warehouse_id = warehouses.id
full join (select
warehouses.id as id,
count(pallets.id) as out,
to_char(pallets.out_date, 'FMMonth-YY') as out_month
from pallets
inner join reservations
on pallets.reservation_id = reservations.id
inner join warehouses
on reservations.warehouse_id = warehouses.id
where pallets.in_date is not null and pallets.out_date is not null
group by
date_part('month', pallets.out_date),
date_part('year', pallets.out_date),
to_char(pallets.out_date, 'FMMonth-YY'),
warehouses.id
order by
date_part('year', pallets.out_date),
date_part('month', pallets.out_date)) as out
on out.id=warehouses.id
where pallets.in_date is not null
group by
warehouses.id,
date_part('month', pallets.in_date),
date_part('year', pallets.in_date),
to_char(pallets.in_date, 'FMMonth-YY')
order by
date_part('year', pallets.in_date),
date_part('month', pallets.in_date)
我有什么想法可以做到这一点吗?
答案 0 :(得分:0)
WITH
inbound AS (
SELECT
warehouses.id,
count(pallets.id),
to_char(pallets.in_date, 'FMMonth-YY') AS in_month
FROM
pallets
INNER JOIN
reservations
ON pallets.reservation_id = reservations.id
INNER JOIN
warehouses
ON reservations.warehouse_id = warehouses.id
WHERE pallets.in_date is not null
GROUP BY
warehouses.id,
date_part('month', pallets.in_date),
date_part('year', pallets.in_date),
to_char(pallets.in_date, 'FMMonth-YY')),
outbound AS (
SELECT
warehouses.id as id,
count(pallets.id),
to_char(pallets.out_date, 'FMMonth-YY') AS out_month
FROM
pallets
INNER JOIN
reservations
ON pallets.reservation_id = reservations.id
INNER JOIN
warehouses
ON reservations.warehouse_id = warehouses.id
WHERE pallets.in_date is not null and pallets.out_date is not null
GROUP BY
date_part('month', pallets.out_date),
date_part('year', pallets.out_date),
to_char(pallets.out_date, 'FMMonth-YY'),
warehouses.id)
SELECT
coalesce(a.id, b.id) AS warehouse_id,
coalesce(a.in_month, b.out_month) AS which_month,
coalesce(a.count, 0) AS inbound,
coalesce(b.count, 0) AS outbound
FROM
inbound AS a
FULL JOIN
outbound AS b ON a.id = b.id AND a.in_month = b.out_month;
答案 1 :(得分:0)
实现此目的的一种方法是使用现有查询(稍作修改)作为内联视图。并使用FULL OUTER JOIN操作来组合它们。
没有给出Warehouse_id是否为NULL的指示,因此代替相等比较,下面的示例使用“null-safe”比较,因此warehouse_id的NULL值将通过join操作“匹配”。 / p>
而不是使用DATE_PART和DATE_FORMAT,只需在内联视图中使用DATE_TRUNC函数。这样可以更容易地进行连接,并且可以使用该值来排序结果(如果这很重要)并将月份作为格式化字符串返回。如果将其存储为表,我将存储日期值,而不是格式化的字符串。
我也更喜欢使用短表别名来限定列引用。
select coalesce(i.warehouse_id,o.warehouse_id) as warehouse_id
, coalesce(i.in_month,o.out_month) as month_
, to_char(coalesce(i.in_month,o.out_month), 'FMMonth-YY') as month_yy
, coalesce(i.cnt,0) as in_count
, coalesce(o.cnt,0) as out_count
from ( select w.id as warehouse_id
, date_trunc('month', p.in_date) as in_month
, count(p.id) as cnt
from pallets p
join reservations r
on r.id = p.reservation_id
join warehouses w
on w.id = r.warehouse_id
where p.in_date is not null
group by w.id
, date_trunc('month', p.in_date)
) i
full
join ( select w.id as warehouse_id
, date_trunc('month', p.out_date) as out_month
, count(p.id) as cnt
from pallets p
join reservations r
on r.id = p.reservation_id
join warehouses w
on w.id = r.warehouse_id
where p.in_date is not null
and p.out_date is not null
group
by w.id
, date_trunc('month', p.out_date)
) o
on o.warehouse_id is not distinct from i.warehouse_id
and o.out_month = i.in_month
order by coalesce(i.warehouse_id,o.warehouse_id)
, coalesce(i.in_month,o.out_month)
我个人的偏好是使用大写字母来表示函数,关键字和保留字。
SELECT COALESCE(i.warehouse_id,o.warehouse_id) AS warehouse_id
, COALESCE(i.in_month,o.out_month) AS month_
, TO_CHAR(COALESCE(I.IN_MONTH,O.OUT_MONTH), 'FMMonth-YY') AS month_yy
, COALESCE(i.cnt,0) AS in_count
, COALESCE(o.cnt,0) AS out_count
FROM ( SELECT w.id AS warehouse_id
, DATE_TRUNC('month', p.in_date) AS in_month
, COUNT(p.id) AS cnt
FROM pallets p
JOIN reservations r
ON r.id = p.reservation_id
JOIN warehouses w
ON w.id = r.warehouse_id
WHERE p.in_date IS NOT NULL
GROUP BY w.id
, DATE_TRUNC('month', p.in_date)
) i
FULL
JOIN ( SELECT w.id AS warehouse_id
, DATE_TRUNC('month', p.out_date) AS out_month
, COUNT(p.id) AS cnt
FROM pallets p
JOIN reservations r
ON r.id = p.reservation_id
JOIN warehouses w
ON w.id = r.warehouse_id
WHERE p.in_date IS NOT NULL
AND p.out_date IS NOT NULL
GROUP BY w.id
, DATE_TRUNC('month', p.out_date)
) o
ON o.warehouse_id IS NOT DISTINCT FROM i.warehouse_id
AND o.out_month = i.in_month
ORDER BY COALESCE(i.warehouse_id,o.warehouse_id)
, COALESCE(i.in_month,o.out_month)
答案 2 :(得分:0)
为简化查询,我认为您可以这样欺骗COUNT:
注意:WITH子句内的查询对您来说已经足够了。但是我添加了WITH子句以便能够建立联合。这取决于你想要输出的内容。
WITH computed_warehouses AS (
-- Maybe this single select (inside the WITH is what you want)
select
warehouses.id,
count(pallets.id) as nb_in_date,
count(pallets.id||pallets.out_date) as nb_out_date,
-- Edit: count(pallets.out_date) as nb_out_date should also work and it's simpler
to_char(pallets.in_date, 'FMMonth-YY') as in_month,
to_char(pallets.out_date, 'FMMonth-YY') as out_month
from pallets
inner join reservations
on pallets.reservation_id = reservations.id
inner join warehouses
on reservations.warehouse_id = warehouses.id
where pallets.in_date is not null
group by
warehouses.id,
date_part('month', pallets.in_date),
date_part('year', pallets.in_date),
to_char(pallets.in_date, 'FMMonth-YY'),
to_char(pallets.out_date, 'FMMonth-YY')
order by
date_part('year', pallets.in_date),
date_part('month', pallets.in_date)
)
-- If you wanna make a union
(
SELECT
t.id AS warehouse_id,
t.in_month AS which_month,
t.nb_in_date AS inbound,
NULL AS outbound
FROM computed_warehouses t
)
UNION ALL
(
SELECT
t.id AS warehouse_id,
t.out_month AS which_month,
NULL AS inbound,
t.nb_out_date AS outbound
FROM computed_warehouses t
WHERE t.nb_out_date IS NOT NULL
AND t.nb_out_date > 0
)
count(pallets.id || pallets.out_date)有点棘手,只计算out_date不为空的托盘。它可以很好地工作,因为 id 和 out_date 属于同一个表,因为当空值时count不会递增。
修改:
count(pallets.out_date) as nb_out_date
应该也可以工作,更简单,也应该更快