簡體   English   中英

count()大於平均值

[英]Having count() greater than average of

我正在嘗試解決以下SQL查詢,該查詢應該顯示比去年所有設備的平均故障數量更多的設備數據,而我對此有些猶豫。

到目前為止,我已經提出了:

select e.equipment_id ,
       e.equipment_name ,
       e.equipment_serialnum ,
       e.equipment_descrip
from equipment e ,
     problems  p
where e.equipment_id       = p.equipment_id
  and year( problem_date ) = year( getdate() )
group by e.equipment_id   ,
         e.equipment_name ,
         e.equipment_serialnum ,
         e.equipment_descrip
having count(p.problem_id) > ( select avg( pnumber )
                               from ( SELECT p1.problem_id ,
                                             COUNT( p1.problem_id ) AS pnumber
                                      FROM problems  p1
                                      JOIN equipment e1 ON e1.equipment_id = p1.equipment_id
                                                       and year( p1.problem_date ) = 2013
                                      GROUP BY p1.problem_id
                                    )

但它不起作用。 這是查詢中涉及的表的結構

problems
(
  problem_id      integer  not null identity(1,1)
  equipment_id    integer  not null,
  user_id         integer  not null,
  problem_date    datetime not null,
  problem_descrip varchar(255)
)

equipment
(
  equipment_id        integer    not null identity(1,1) ,
  equipment_type_cod  char(20)   not null ,
  equipment_bought    datetime   not null ,
  equipment_available datetime   ,
  equipment_serialnum char(20)   ,
  equipment_name    varchar(255) ,
  equipment_descrip varchar(255)
)

感謝您提供的任何幫助。

您的子選擇需要一個表名

( select avg( pnumber )
    from ( SELECT p1.problem_id ,
             COUNT( p1.problem_id ) AS pnumber
      FROM problems  p1
      JOIN equipment e1 ON e1.equipment_id = p1.equipment_id
                       and year( p1.problem_date ) = 2013
      GROUP BY p1.problem_id
    ) x
)

首先,讓我們創建模式:

create table dbo.equipment
(
  equipment_id        integer      not null identity(1,1) primary key clustered ,
  equipment_type_cod  char(20)     not null ,
  equipment_bought    datetime     not null ,
  equipment_available datetime              ,
  equipment_serialnum char(20)              ,
  equipment_name      varchar(255)          ,
  equipment_descrip   varchar(255)          ,
)
go

create table dbo.problems
(
  problem_id      integer      not null identity(1,1) primary key clustered ,
  equipment_id    integer      not null foreign key references dbo.equipment( equipment_id ) ,
  user_id         integer      not null ,
  problem_date    datetime     not null ,
  problem_descrip varchar(255)          ,
)
go

將我們的問題分解成較小的離散塊通常會很有幫助。 SQL Server的with子句在這里很有用,因為它提供了一種定義名稱虛擬表的便捷方法:

with
--
-- a 1-row table containing the starting date for the previous, current and next years
--
year_start as (
  select prev = convert(date,datename(year,dateadd(year, -1 , current_timestamp))) ,
         curr = convert(date,datename(year,dateadd(year,  0 , current_timestamp))) ,
         next = convert(date,datename(year,dateadd(year, +1 , current_timestamp)))
) ,
--
-- the count of problems per unit over the previous year. This
-- uses a left join to include those pieces of equipment that had no problems.
-- Depending on you requirement, you might want to change that to an inner join.
--
prev_year_problems as (
  select equipment_id = e.equipment_id ,
         problem_cnt  = coalesce( p.problems , 0 )
  from dbo.equipment e
  left join ( select equipment_id = p.equipment_id ,
                     problems     = count(*)
              from       dbo.problems p
              cross join year_start   y
              where p.problem_date >= y.prev
                and p.problem_date <  y.curr
              group by p.equipment_id
            ) p on p.equipment_id = e.equipment_id
) ,
--
-- the count of problems per unit in the current year, up to the current date.
-- This is essentially identical to the previous CTE, with the exception of
-- the boundaries of the desired date range.
--
curr_year_problems as (
  select equipment_id = e.equipment_id ,
         problem_cnt  = coalesce( p.problems , 0 )
  from dbo.equipment e
  left join ( select equipment_id = p.equipment_id ,
                     problems     = count(*)
              from       dbo.problems p
              cross join year_start   y
              where p.problem_date >= y.curr
                and p.problem_date <  y.next
              group by p.equipment_id
            ) p on p.equipment_id = e.equipment_id
) ,
--
-- Here, we roll the previous year's problem counts up and summarize them into
-- a single row table containing the mean number of problems per unit over the year.
--
previous_year_summary as (
  select mean_problems_per_unit = avg( t.problem_cnt )
  from prev_year_problems t
)
--
-- Finally, we select the rows from the equipment table that meet the defined
-- criteria
--
select e.* ,
       curr_year_problems_to_date       = cyp.problem_cnt ,
       prev_year_mean_problems_per_unit = ps.mean_problems_per_unit
from dbo.equipment         e
join curr_year_problems    cyp on cyp.equipment_id = e.equipment_id
join previous_year_summary ps  on cyp.problem_cnt > ps.mean_problems_per_unit

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM