无法按查询分组获取MySQL中的某些字段

时间:2019-03-02 11:09:51

标签: mysql group-by

我有以下查询(并尝试了很多变体) :

select housedata.housecode, housedata.name, min((pergroup + (perguest *  GREATEST((2 - guests_included),0)))) as mincalculated 
from housedata
inner join availabilitydata 
where housedata.housecode = availabilitydata.housecode 
and  datediff(departure, arrival) = 7 group by housedata.housecode

这工作正常,但我需要表Availabilitydata中的更多字段。一旦我尝试添加这些MySQL抱怨:

  

[42000] [1055] SELECT列表的表达式#4不在GROUP BY子句中,并且包含未聚合的列“ houses.availabilitydata.arrival”,该列在功能上不依赖于GROUP BY子句中的列;这与sql_mode = only_full_group_by

不兼容

我可以将字段添加到组中,但是由于可用性数据是多行,所以我得到的结果却多于一个。

如何将其限制为每所房子一行,即从哪一行获得min((pergroup +(perguest * GREATEST((2-guests_included),0))))。

表格:

create table availabilitydata
(
  arrival              date        not null,
  departure            date        not null,
  housecode            varchar(32) not null,
  pergroup             float       null,
  pergroupexcldiscount float       null,
  perguest             float       null,
  guests_included      tinyint     null,
  primary key (housecode, arrival, departure)
);

create table housedata
(
  housecode       varchar(32) not null
    primary key,
  name            tinytext    null
);

数据应该这样显示,但要添加日期列:

344323  Wienerwaltz 680.530029296875
434300  Wald    882.7899780273438
943843  Chalet Miquel   630.8300170898438

2 个答案:

答案 0 :(得分:0)

您需要在添加到SQL的列(字段)上使用聚合函数:未聚合的列(在标准SQL中,但mySQL仍然接受SQL,具体取决于sql_mode设置)在GROUP BY列。

最后,如果您想添加availabilitydata表列,并且不介意显示同一组中的多个记录中的哪一个,则应使用MIN(availabilitydata.col1), MIN(availabilitydata.col2), ...并始终列出所有未聚合的列在GROUP BY语句中:

select housedata.housecode, 
       housedata.name,
       min(availabilitydata.col1) as  availabilitydata_col1_min,
       min(availabilitydata.col2) as  availabilitydata_col2_min,
       ...,
       min((pergroup + (perguest *  GREATEST((2 - guests_included),0)))) as mincalculated 
from housedata
inner join availabilitydata 
where housedata.housecode = availabilitydata.housecode 
and  datediff(departure, arrival) = 7 
group by housedata.housecode,housedata.name

答案 1 :(得分:0)

尝试一下:

select h.housecode
     , hh.name
     , pergroup + (perguest *  GREATEST((2 - guests_included),0)) as mincalculated
     -- select any column from a (availabilitydata)
from housedata h
inner join availabilitydata a on a.housecode = h.housecode 
where (a.housecode, a.arrival, a.departure) = (
    select a2.housecode, a2.arrival, a2.departure
    from availabilitydata a2
    where a2.housecode = h.housecode
      and datediff(a2.departure, a2.arrival) = 7
    order by a2.pergroup + (a2.perguest *  GREATEST((2 - a2.guests_included),0)) asc
    limit 1
)

在相关子查询中,您将获得具有最小计算值的行的主键(a.housecode, a.arrival, a.departure)。在外部查询中,您仅从availabilitydata中选择具有相同主键的行。

请注意,如果两行具有相同的计算最小值,则将同时获得它们。如果您不想两者都使用,则应在ORDER BY子句中定义所需的对象(例如,添加完整的主键):

order by a2.pergroup + (a2.perguest *  GREATEST((2 - a2.guests_included),0)) asc
    , a2.arrival
    , a2.departure

更新

上述解决方案似乎效果不佳。但是,如果您的版本支持窗口功能,则还可以使用以下查询:

select *
from (
    select housedata.housecode
         , housedata.name
         , pergroup + (perguest *  GREATEST((2 - guests_included),0)) as mincalculated
         , row_number() over (
             partition by housedata.housecode
             order by pergroup + (perguest *  GREATEST((2 - guests_included),0)) asc
         ) rn
         , availabilitydata.arrival
         -- select any other column from availabilitydata
    from housedata
    inner join availabilitydata on housedata.housecode = availabilitydata.housecode 
    where datediff(departure, arrival) = 7
) x
where rn = 1