有没有办法只显示第一个非零值,但如果所有值都为零,则在单独的 table 中显示列的第一个实例,而不是加入 tables
Is there a way to only show first non-zero value but if all values are zero then show 1st instance of a column in a separate table from joining tables
这两个 table 相当大,我的 select 语句有更多我获得的值,但我想我可以简化这些数据和查询,这样我的问题就可以得到回答。
这是我的 select 声明:
SELECT invoice.InvoiceNum, Layer, InvoiceItemNum
FROM (INVOICE
left outer join InvoiceItem item
ON item.InvoiceNum = Invoice.InvoiceNum
)
ORDER BY invoice.InvoiceNum
所以我有两个 table。发票 table 和 InvoiceItem table。它们由每个 table 中的 InvoiceNum 列连接,并显示 InvoiceNum 和 Layer Column
这是此查询的结果:
InvoiceNum | Layer | InvoiceItemNum
1 | 10 | 1
1 | 0 | 2
1 | 7 | 3
1 | 0 | 4
2 | 0 | 1
2 | 3 | 2
3 | 0 | 1
3 | 0 | 2
3 | 0 | 3
4 | 0 | 1
4 | 0 | 2
4 | 5 | 3
因为我的 InvoiceItem table 有多行可以分配给 1 InvoiceNum 这导致我的结果中有重复的 invoiceNums,这是我不想要的。
这是我试图获得的结果,仅列出发票 table 中的 1 个 invoiceNum,第一种情况是 InvoiceItem table 的图层列中的非零值, 如果没有非零则列出第一个零。
正在尝试这样的事情:
InvoiceNum | Layer | InvoiceItemNum
1 | 10 | 1
2 | 3 | 2
3 | 0 | 1
4 | 5 | 3
我只是不确定该怎么做,或者这是否可行,因为它们位于两个不同的 tables 上。
你试过 ASC 和 DESC 吗?
SELECT invoice.InvoiceNum, Layer, InvoiceItemNum
FROM (INVOICE
left outer join InvoiceItem item
ON item.InvoiceNum = Invoice.InvoiceNum
)
ORDER BY Layer DESC, invoice.InvoiceNum ASC
这个问题有点棘手:
在 Postgres 中试试这个:
with cte as (
select
inv.invoicenum,sum(layer::int) "sum_layer"
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
group by 1
)
,
cte1 as (
select distinct on (inv.invoicenum) inv.invoicenum,layer, InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer=0)
order by inv.invoicenum, InvoiceItemNum
),
cte2 as (
select
distinct on (inv.invoicenum) inv.invoicenum, layer , InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer>0) and layer::int>0
order by inv.invoicenum, InvoiceItemNum
)
(
select * from cte1
union all
select * from cte2
)
order by 1
在MySQL 8:
试试这个:
with cte as (
select
inv.invoicenum,sum(layer) "sum_layer"
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
group by 1
)
,
cte1 as (
select * from (
select inv.invoicenum, layer, InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer=0)
order by inv.invoicenum, InvoiceItemNum
) c
group by invoicenum
),
cte2 as (
select * from (
select inv.invoicenum, layer, InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer>0) and layer>0
order by inv.invoicenum, InvoiceItemNum ) c
group by invoicenum
)
(
select * from cte1
union all
select * from cte2
)
Assumptions/Understandings:
- 虽然用
sybase
标记,但该问题并未区分 4 种不同的 Sybase RDBMS 产品(ASE
、SQLAnywhere
、IQ
、Advantage
)所以我将坚持使用通用的 SQL 语法(即,4x 产品具有不同的 SQL 方言;此外,ASE 不支持 CTE)
- 我不明白 OP 对
left (outer) join
的使用,因为提供的输出似乎没有表明来自 InvoiceItem
的任何 'missing' 行
- 不清楚 table
Layer
和 InvoiceItemNum
列属于哪个,所以我假设它们属于 InvoiceItem
猜测一组最小 table 定义和关联的 insert
语句:
create table Invoice
(InvoiceNum int
)
create table InvoiceItem
(InvoiceNum int
,InvoiceItemNum int
,Layer int
)
insert Invoice select 1 union all select 2 union all select 3 union all select 4
insert InvoiceItem values (1,1,10)
insert InvoiceItem values (1,2,0)
insert InvoiceItem values (1,3,7)
insert InvoiceItem values (1,4,0)
insert InvoiceItem values (2,1,0)
insert InvoiceItem values (2,2,3)
insert InvoiceItem values (3,1,0)
insert InvoiceItem values (3,2,0)
insert InvoiceItem values (3,3,0)
insert InvoiceItem values (4,1,0)
insert InvoiceItem values (4,2,0)
insert InvoiceItem values (4,3,5)
生成 OP 当前输出的查询:
select inv.InvoiceNum,
item.Layer,
item.InvoiceItemNum
from Invoice inv
left -- superfluous in this case?
join InvoiceItem item
on inv.InvoiceNum = item.InvoiceNum
order by 1,3
InvoiceNum Layer InvoiceItemNum
----------- ----------- --------------
1 10 1
1 0 2
1 7 3
1 0 4
2 0 1
2 3 2
3 0 1
3 0 2
3 0 3
4 0 1
4 0 2
4 5 3
生成 OP 所需输出的几个不同(复杂、混乱)想法:
-- join based on Layer!=0; if no rows found then override NULLs
-- with Layer=0 and InvoiceItemNum=min(InvoiceItemNum) where Layer=0;
-- needs more work in case there are no matching rows in InvoiceItem ...
-- wrap case/then in a coalesce() and set to, what, 0?
select inv.InvoiceNum,
coalesce(item1.Layer,0) as "Layer",
case when item1.InvoiceItemNum is NULL
then (select min(InvoiceItemNum) from InvoiceItem item3 where item3.InvoiceNum = inv.InvoiceNum)
else item1.InvoiceItemNum
end as "InvoiceItemNum"
from Invoice inv
left
join InvoiceItem item1
on inv.InvoiceNum = item1.InvoiceNum
and item1.Layer != 0
and not exists(select 1
from InvoiceItem item2
where item2.InvoiceNum = item1.InvoiceNum
and item2.Layer != 0
and item2.InvoiceItemNum < item1.InvoiceItemNum)
order by 1
-- OR
-- perform a mutually exclusive UNION of Layer!=0 and Layer=0 queries
-- with Layer!=0 having prcedence
select inv.InvoiceNum,
item1.Layer,
item1.InvoiceItemNum
from Invoice inv
--left ??? needs work if this is really an outer join ???
join InvoiceItem item1
on inv.InvoiceNum = item1.InvoiceNum
and (
( item1.Layer != 0
and not exists(select 1
from InvoiceItem item2
where item2.InvoiceNum = item1.InvoiceNum
and item2.Layer != 0
and item2.InvoiceItemNum < item1.InvoiceItemNum)
)
or
( item1.Layer = 0
and not exists(select 1
from InvoiceItem item3
where item3.InvoiceNum = item1.InvoiceNum
and item3.Layer != 0)
and not exists(select 1
from InvoiceItem item4
where item4.InvoiceNum = item1.InvoiceNum
and item4.Layer = 0
and item4.InvoiceItemNum < item1.InvoiceItemNum)
)
)
order by 1
这两个都会生成:
InvoiceNum Layer InvoiceItemNum
----------- ----------- --------------
1 10 1
2 3 2
3 0 1
4 5 3
备注:
- 不确定输出应该是什么,因为它没有出现(对我来说)OP 已经证明需要
left (outer) join
- 在 (Sybase)SAP 中测试的所有查询
ASE 16.0
这两个 table 相当大,我的 select 语句有更多我获得的值,但我想我可以简化这些数据和查询,这样我的问题就可以得到回答。
这是我的 select 声明:
SELECT invoice.InvoiceNum, Layer, InvoiceItemNum
FROM (INVOICE
left outer join InvoiceItem item
ON item.InvoiceNum = Invoice.InvoiceNum
)
ORDER BY invoice.InvoiceNum
所以我有两个 table。发票 table 和 InvoiceItem table。它们由每个 table 中的 InvoiceNum 列连接,并显示 InvoiceNum 和 Layer Column
这是此查询的结果:
InvoiceNum | Layer | InvoiceItemNum
1 | 10 | 1
1 | 0 | 2
1 | 7 | 3
1 | 0 | 4
2 | 0 | 1
2 | 3 | 2
3 | 0 | 1
3 | 0 | 2
3 | 0 | 3
4 | 0 | 1
4 | 0 | 2
4 | 5 | 3
因为我的 InvoiceItem table 有多行可以分配给 1 InvoiceNum 这导致我的结果中有重复的 invoiceNums,这是我不想要的。
这是我试图获得的结果,仅列出发票 table 中的 1 个 invoiceNum,第一种情况是 InvoiceItem table 的图层列中的非零值, 如果没有非零则列出第一个零。
正在尝试这样的事情:
InvoiceNum | Layer | InvoiceItemNum
1 | 10 | 1
2 | 3 | 2
3 | 0 | 1
4 | 5 | 3
我只是不确定该怎么做,或者这是否可行,因为它们位于两个不同的 tables 上。
你试过 ASC 和 DESC 吗?
SELECT invoice.InvoiceNum, Layer, InvoiceItemNum
FROM (INVOICE
left outer join InvoiceItem item
ON item.InvoiceNum = Invoice.InvoiceNum
)
ORDER BY Layer DESC, invoice.InvoiceNum ASC
这个问题有点棘手:
在 Postgres 中试试这个:
with cte as (
select
inv.invoicenum,sum(layer::int) "sum_layer"
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
group by 1
)
,
cte1 as (
select distinct on (inv.invoicenum) inv.invoicenum,layer, InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer=0)
order by inv.invoicenum, InvoiceItemNum
),
cte2 as (
select
distinct on (inv.invoicenum) inv.invoicenum, layer , InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer>0) and layer::int>0
order by inv.invoicenum, InvoiceItemNum
)
(
select * from cte1
union all
select * from cte2
)
order by 1
在MySQL 8:
试试这个:
with cte as (
select
inv.invoicenum,sum(layer) "sum_layer"
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
group by 1
)
,
cte1 as (
select * from (
select inv.invoicenum, layer, InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer=0)
order by inv.invoicenum, InvoiceItemNum
) c
group by invoicenum
),
cte2 as (
select * from (
select inv.invoicenum, layer, InvoiceItemNum
from invoice inv inner join invoiceitem item on item.invoicenum=inv.invoicenum
where inv.invoicenum in (select invoicenum from cte where sum_layer>0) and layer>0
order by inv.invoicenum, InvoiceItemNum ) c
group by invoicenum
)
(
select * from cte1
union all
select * from cte2
)
Assumptions/Understandings:
- 虽然用
sybase
标记,但该问题并未区分 4 种不同的 Sybase RDBMS 产品(ASE
、SQLAnywhere
、IQ
、Advantage
)所以我将坚持使用通用的 SQL 语法(即,4x 产品具有不同的 SQL 方言;此外,ASE 不支持 CTE) - 我不明白 OP 对
left (outer) join
的使用,因为提供的输出似乎没有表明来自InvoiceItem
的任何 'missing' 行
- 不清楚 table
Layer
和InvoiceItemNum
列属于哪个,所以我假设它们属于InvoiceItem
猜测一组最小 table 定义和关联的 insert
语句:
create table Invoice
(InvoiceNum int
)
create table InvoiceItem
(InvoiceNum int
,InvoiceItemNum int
,Layer int
)
insert Invoice select 1 union all select 2 union all select 3 union all select 4
insert InvoiceItem values (1,1,10)
insert InvoiceItem values (1,2,0)
insert InvoiceItem values (1,3,7)
insert InvoiceItem values (1,4,0)
insert InvoiceItem values (2,1,0)
insert InvoiceItem values (2,2,3)
insert InvoiceItem values (3,1,0)
insert InvoiceItem values (3,2,0)
insert InvoiceItem values (3,3,0)
insert InvoiceItem values (4,1,0)
insert InvoiceItem values (4,2,0)
insert InvoiceItem values (4,3,5)
生成 OP 当前输出的查询:
select inv.InvoiceNum,
item.Layer,
item.InvoiceItemNum
from Invoice inv
left -- superfluous in this case?
join InvoiceItem item
on inv.InvoiceNum = item.InvoiceNum
order by 1,3
InvoiceNum Layer InvoiceItemNum
----------- ----------- --------------
1 10 1
1 0 2
1 7 3
1 0 4
2 0 1
2 3 2
3 0 1
3 0 2
3 0 3
4 0 1
4 0 2
4 5 3
生成 OP 所需输出的几个不同(复杂、混乱)想法:
-- join based on Layer!=0; if no rows found then override NULLs
-- with Layer=0 and InvoiceItemNum=min(InvoiceItemNum) where Layer=0;
-- needs more work in case there are no matching rows in InvoiceItem ...
-- wrap case/then in a coalesce() and set to, what, 0?
select inv.InvoiceNum,
coalesce(item1.Layer,0) as "Layer",
case when item1.InvoiceItemNum is NULL
then (select min(InvoiceItemNum) from InvoiceItem item3 where item3.InvoiceNum = inv.InvoiceNum)
else item1.InvoiceItemNum
end as "InvoiceItemNum"
from Invoice inv
left
join InvoiceItem item1
on inv.InvoiceNum = item1.InvoiceNum
and item1.Layer != 0
and not exists(select 1
from InvoiceItem item2
where item2.InvoiceNum = item1.InvoiceNum
and item2.Layer != 0
and item2.InvoiceItemNum < item1.InvoiceItemNum)
order by 1
-- OR
-- perform a mutually exclusive UNION of Layer!=0 and Layer=0 queries
-- with Layer!=0 having prcedence
select inv.InvoiceNum,
item1.Layer,
item1.InvoiceItemNum
from Invoice inv
--left ??? needs work if this is really an outer join ???
join InvoiceItem item1
on inv.InvoiceNum = item1.InvoiceNum
and (
( item1.Layer != 0
and not exists(select 1
from InvoiceItem item2
where item2.InvoiceNum = item1.InvoiceNum
and item2.Layer != 0
and item2.InvoiceItemNum < item1.InvoiceItemNum)
)
or
( item1.Layer = 0
and not exists(select 1
from InvoiceItem item3
where item3.InvoiceNum = item1.InvoiceNum
and item3.Layer != 0)
and not exists(select 1
from InvoiceItem item4
where item4.InvoiceNum = item1.InvoiceNum
and item4.Layer = 0
and item4.InvoiceItemNum < item1.InvoiceItemNum)
)
)
order by 1
这两个都会生成:
InvoiceNum Layer InvoiceItemNum
----------- ----------- --------------
1 10 1
2 3 2
3 0 1
4 5 3
备注:
- 不确定输出应该是什么,因为它没有出现(对我来说)OP 已经证明需要
left (outer) join
- 在 (Sybase)SAP 中测试的所有查询
ASE 16.0