如何列出各个列,其中每个列都包含一个id计数,其中每列中的ID“不在”MySQL中

时间:2018-03-29 22:47:34

标签: mysql notin

我正在尝试运行以下查询以确定在特定日期我在某个区域中尚未预订的可用供应量。我这样做是通过按地区和可用天数生成所有工人的表格,并使用“在哪里”确保他们“不在”那天确认的预订表中。

我有两个问题:

  1. 这只能在1天内给我剩余的可用电量。我希望能够在一系列日子里显示剩余的可用供应量。例如。未来三天第1天,第2天和第3天的剩余可用供应量。这意味着我必须迭代地将我的工人名单与每天的预订表进行比较。所以col1会计算工人ID'不在'Day1的预订表中,而工作人员在Day1s工作,col2将计算工人ID'不在'Day2的预订表中,工人在Day2s工作,等等。

  2. 这是一个更小的问题。给定下面的代码,如果可用电源的计数为0,则该区域行不在结果表中。我试图在计数上使用IFNULL,但这不起作用。因此,我必须在该查询和查询之间创建一个联合,该查询列出所有具有0值的区域,然后选择具有最大值的每个区域。有更好的方法吗?

  3. [daterange_start]字段是由仪表板的最终用户替换的过滤字段。

    select 
        area, 
        MAX(man_days_remaining)
    from (
    select doa.zip_code as area, count(w.user_ptr_id) as man_days_remaining
    from domestic_worker w 
    left join domestic_worker_worker_operating_areas dwoa 
        on w.user_ptr_id = dwoa.worker_id 
    left join geography_operatingarea doa 
        on doa.id = dwoa.operatingarea_id 
    left join domestic_worker_days_available d 
        on w.user_ptr_id = d.worker_id 
    left join geography_city c 
        on c.id = w.worker_city_id
    where w.user_ptr_id not in (
        select w.user_ptr_id 
        from booking_booking b 
        left join domestic_jobcard j 
        on b.id = j.booking_id 
        left join domestic_worker w 
        on w.user_ptr_id = j.worker_id 
        where date(b.appointment_datetime) = date([daterange_start]) 
        and b.booking_status = 'confirmed' 
        and w.user_ptr_id is not null) 
    and weekday([daterange_start]) + 1 = d.weekday_id
    group by 1
    UNION
    select doa.zip_code as 'Area', '0', null
    from geography_operatingarea doa
    where doa.active = 1
    ) t
    group by 1
    order by 1 asc
    

1 个答案:

答案 0 :(得分:0)

规范并不完全清楚。模式定义,样本数据和预期输出的例子将大大有助于澄清它。

所以,我们只是在猜测。

我的猜测是这样的东西会满足要求:

SELECT t.zip_code AS area
     , MAX(IF(t.i=0,man_days_remaining,0)) AS d0_mdr  -- day 0 man days remaining
     , MAX(IF(t.i=1,man_days_remaining,0)) AS d1_mdr  -- day 1 man days remaining
     , MAX(IF(t.i=2,man_days_remaining,0)) AS d2_mdr  -- day 2 man days remaining
     , MAX(IF(t.i=3,man_days_remaining,0)) AS d3_mdr  -- day 3 man days remaining
 FROM (
        SELECT doa.zip_code
             , n.i
             , COUNT(DISTINCT w.user_ptr_id) AS man_days_remaining
          FROM ( SELECT DATE([daterange_start]) + INTERVAL 0 DAY AS dt ) i
         CROSS
          JOIN ( SELECT 0 AS i
                 UNION ALL SELECT 1
                 UNION ALL SELECT 2
                 UNION ALL SELECT 3
                 UNION ALL SELECT NULL
               ) n
          JOIN geography_operatingarea doa
            ON doa.active = 1
          LEFT
          JOIN domestic_worker_worker_operating_areas dwoa
            ON dwoa.operatingarea_id = doa.id
          LEFT
          JOIN domestic_worker w
            ON w.user_ptr_id = dwoa.worker_id
          LEFT
          JOIN domestic_worker_days_available d
            ON d.worker_id = w.user_ptr_id
           AND d.weekday_id = WEEKDAY(i.dt + INTERVAL n.i DAY) + 1

            -- anti-join confirmed booking
          LEFT
          JOIN domestic_jobcard dj
            ON dj.worker_id = d.worker_id
          LEFT
          JOIN booking_booking bb
            ON bb.id = dj.booking_id
           AND bb.booking_status = 'confirmed'
           AND DATE(bb.appointment_datetime) = i.dt + INTERVAL n.i DAY
         WHERE bb.id IS NULL

         GROUP
            BY doa.zip_code
             , n.i
        ) t
  GROUP BY t.zip_code

这是使用内联视图(n)返回0到3的整数值。我们将[daterange_start]添加该值以检查四个日期,从{{开始1}}。

然后我们可以将该套装加入所有活跃的' DOA。

外部联接,以获取在这些日期可用的所有[daterange_start]的集合。

然后我们可以使用反连接模式排除任何domestic_worker 确认预订的日期。

然后我们可以获得每天可用工人的数量。

边缘案例是doa,该区域的所有工作人员已经预订了所有四天,查询将不会返回该doa。我们可以做一个黑客为每个zip_code包含额外的行...保证不与任何工人匹配或预订的行,并且不会包含在任何计数中。一种快速的方法是在我们生成的整数集中包含NULL值。

然后我将该结果包装为内联视图,然后使用条件聚合来获取每天剩余的工作日数,每个邮政编码的单行。

这种方法可以扩展到任意天数,方法是在生成的集合中添加额外的整数(4,5,...),并在外部查询的SELECT列表中添加表达式。

这可能不符合规范。我对它的理解非常有限,但这就是我如何处理它。

作为反连接的替代方法,我们可以使用带有相关子查询的domestic_worker谓词:

NOT EXISTS