2017-05-08 29 views
0

我有一个表lot_bill_of_operations与行和表lot_bill_of_lots_serial_xref其中有序列号和时间戳列。这些表格通过主键bol_id相关联。加入两个表,在三个列的行数列其中的语句

我想计算三个班次按行传递有多少个序列号,但每个子查询都有相同的结果。

下面是该查询:

select lot_bill_of_operations.wc_line_code, 

(select count(part_sn) from lot_bill_of_lots_serial_xref 
    where lot_bill_of_lots_serial_xref.time_stamp between '07-MAY-17 06:00:00' 
    and '07-MAY-17 14:00:00' 
    group by lot_bill_of_operations.wc_line_code)firstshift, 

(select count(part_sn) from lot_bill_of_lots_serial_xref 
    where lot_bill_of_lots_serial_xref.time_stamp between '07-MAY-17 14:00:00' 
    and '07-MAY-17 22:00:00' 
    group by lot_bill_of_operations.wc_line_code)secondshift, 

(select count(part_sn) from lot_bill_of_lots_serial_xref 
    where lot_bill_of_lots_serial_xref.time_stamp between '07-MAY-17 22:00:00' 
    and '08-MAY-17 06:00:00' 
    group by lot_bill_of_operations.wc_line_code)thirdshift 

FROM lot_bill_of_operations inner JOIN lot_bill_of_lots_serial_xref 
    ON lot_bill_of_operations.bol_id = lot_bill_of_lots_serial_xref.bol_id 
group by lot_bill_of_operations.wc_line_code 

这里是获取结果:

enter image description here

我在做什么错?

+0

给一些样本的数据和预期的输出? – Utsav

回答

0

尝试以下操作:

select lot_bill_of_operations.wc_line_code 
, sum (case when time_stamp between '07-MAY-17 06:00:00' and '07-MAY-17 14:00:00' 
then 1 else 0 end) firstshift 
, sum (case when time_stamp between '07-MAY-17 14:00:00' and '07-MAY-17 22:00:00' 
then 1 else 0 end) secondshift 
, sum (case when time_stamp between '07-MAY-17 22:00:00' and '08-MAY-17 06:00:00' 
then 1 else 0 end) thirdshift 
FROM lot_bill_of_operations inner JOIN lot_bill_of_lots_serial_xref 
    ON lot_bill_of_operations.bol_id = lot_bill_of_lots_serial_xref.bol_id 
group by lot_bill_of_operations.wc_line_code 
; 
2

它看起来像你想有条件的计数,这可以用一个CASE表达式得到:

select lbo.wc_line_code, 
    count(case when lblsx.time_stamp between timestamp '2017-05-07 06:00:00' 
    and timestamp '2017-05-07 14:00:00' then lblsx.part_sn end) as firstshift, 
    count(case when lblsx.time_stamp between timestamp '2017-05-07 14:00:00' 
    and timestamp '2017-05-07 22:00:00' then lblsx.part_sn end) as secondshift, 
    count(case when lblsx.time_stamp between timestamp '2017-05-07 22:00:00' 
    and timestamp '2017-05-08 06:00:00' then lblsx.part_sn end) as thirdshift 
from lot_bill_of_operations lbo 
inner join lot_bill_of_lots_serial_xref lblsx 
on lbo.bol_id = lblsx.bol_id 
group by lbo.wc_line_code; 

我切换到时间戳文字,因为你是依靠您的NLS设置将字符串隐式转换为时间戳。 (或者可能是日期,从你所展示的内容来看并不清楚)。

但是,使用between意味着时段稍微重叠,所以你可能真的想:

select lbo.wc_line_code, 
    count(case when lblsx.time_stamp >= timestamp '2017-05-07 06:00:00' 
    and lblsx.time_stamp < timestamp '2017-05-07 14:00:00' then lblsx.part_sn end) as firstshift, 
    count(case when lblsx.time_stamp >= timestamp '2017-05-07 14:00:00' 
    and lblsx.time_stamp < timestamp '2017-05-07 22:00:00' then lblsx.part_sn end) as secondshift, 
    count(case when lblsx.time_stamp >= timestamp '2017-05-07 22:00:00' 
    and lblsx.time_stamp < timestamp '2017-05-08 06:00:00' then lblsx.part_sn end) as thirdshift 
from lot_bill_of_operations lbo 
inner join lot_bill_of_lots_serial_xref lblsx 
on lbo.bol_id = lblsx.bol_id 
group by lbo.wc_line_code; 

您可能还需要包括time_stamp范围内全面过滤,以减少数据的检验量:

... 
where lblsx.time_stamp >= timestamp '2017-05-07 06:00:00' 
and lblsx.time_stamp < timestamp '2017-05-08 06:00:00' 
group by lbo.wc_line_code; 

如果你在这一天的基础上,你可以使用日期算术,而不是固定值。

+1

也许不是问这个问题的正确论坛,但'timestamp'之后的字符串格式将始终为'yyyy-mm-dd hh24:mi:ss',或者取决于NLS设置。 – Utsav

+2

@Utsav - [日期时间ANSI文字](https://docs.oracle.com/database/121/SQLRF/sql_elements003.htm#SQLRF51062)是固定的明确格式,虽然时区信息是可选的。他们根本不依赖于NLS - 这就是为什么我更喜欢他们的静态值(而不是变量)。关于它们的唯一有点恼人的事情是,你不能拥有带时间分量的ANSI日期字面值,你必须使用时间戳字面值(但可以将其转换回日期)。 –

+0

谢谢。好的文章也。我花了太多时间通过'to_date'来投射字符串,我可以避免这种情况。再次感谢。 – Utsav

1

没有样本数据,很难理解你想要什么,但根据你的查询,我相信你需要像下面这样的东西。

  • 还避免比较字符串的日期。使用日期转换函数 类似to_date/to_timestamp,同时比较精确的日期和 的非模糊结果。
  • 使用between同时给出范围。
  • 使用 别名为表名称更好的可读性。

    select o.wc_line_code 
        ,count(case when 
          x.time_stamp between to_date('07-MAY-17 06:00:00','DD-MON-YY HH24:MI:SS') 
              and to_date('07-MAY-17 14:00:00','DD-MON-YY HH24:MI:SS') 
          then 1) as firstshift 
    -- , similary for other shifts 
    
    FROM lot_bill_of_operations o 
        inner JOIN 
        lot_bill_of_lots_serial_xref x 
        ON o.bol_id = x.bol_id 
    group by o.wc_line_code; 
    
+1

我唯一的狡猾与这是继续使用'之间',我意识到是在问题;但正好在14:00点的时间排在第一班和第二班。这*可能是OP想要的,但看起来更像是一场意外。 –

+0

同意。在阅读你的答案之前,我根本没有意识到这一点。我看到你已经清楚地解释了它,所以OP会像我一样了解两者之间的差异。 :) – Utsav