SQL / Spring数据 - 如何根据列中的最小值和不同的id获取完整的行

时间:2016-06-15 02:56:51

标签: sql jpa spring-data spring-data-jpa criteria-api

我有一个观点,集中了我需要的所有数据,以显示一个列表与建立和这个地方最便宜的啤酒。有时我需要根据啤酒的标签和包装过滤最便宜的啤酒的价格和价格,所以,我的观点会返回很多行,结果几乎相同:

Table

标有红色方块的行是我要显示的那些。为了获得图中的结果集,我已经使用了JpaSpecificationExecutor和一些规范,最终的SQL是这样的:

SELECT
  visaoaplic0_.id_estabelecimento   ,
  visaoaplic0_.embalagem_id         ,
  visaoaplic0_.rotulo_id            ,
  visaoaplic0_.nome_cidade          ,
  visaoaplic0_.nome_embalagem       ,
  visaoaplic0_.nome_estabelecimento ,
  visaoaplic0_.nome_estado          ,
  visaoaplic0_.preco                ,
  visaoaplic0_.tipo_estabelecimento,
  visaoaplic0_.icone                ,
  visaoaplic0_.icone_content_type
FROM visao_app_aba_locais visaoaplic0_
WHERE upper(visaoaplic0_.nome_cidade) = 'MONTES CLAROS' AND     upper(visaoaplic0_.nome_estado) = 'MINAS GERAIS' AND
  (upper(visaoaplic0_.nome_estabelecimento) LIKE '%') AND
  (visaoaplic0_.tipo_estabelecimento IN (1006, 1053, 1148, 1008, 1009, 1007)) AND
  (visaoaplic0_.id_estabelecimento IS NOT NULL);

现在的问题是我不知道如何只获取我需要的行,既不使用SQL也不使用条件API。

关于答案

我需要使用JPQL或Criteria API,如果你知道如何只在SQL中解决这个问题,请显示一个独立于数据库供应商的句子(也许在SQL:2011中),所以我可以翻译成JPQL或Criteria API。 / p>

1 个答案:

答案 0 :(得分:0)

所以它可以是SQL还是不可以?以下是一些SQL版本,大多数是针对sql server的,但是一对夫妇可以为任何事情工作。

简单地将行移到顶部的选项:

SELECT
  visaoaplic0_.id_estabelecimento   ,
  visaoaplic0_.embalagem_id         ,
  visaoaplic0_.rotulo_id            ,
  visaoaplic0_.nome_cidade          ,
  visaoaplic0_.nome_embalagem       ,
  visaoaplic0_.nome_estabelecimento ,
  visaoaplic0_.nome_estado          ,
  visaoaplic0_.preco                ,
  visaoaplic0_.tipo_estabelecimento,
  visaoaplic0_.icone                ,
  visaoaplic0_.icone_content_type
  ,RowNum = ROW_NUMBER() OVER (PARTITION BY visaoaplic0_.id_estabelecimento ORDER BY
    IIF(visaoaplic0_.preco IS NULL,1,0) ASC
    ,ISNULL(visaoaplic0_.preco,0) ASC
    )
FROM visao_app_aba_locais visaoaplic0_
WHERE upper(visaoaplic0_.nome_cidade) = 'MONTES CLAROS' AND     upper(visaoaplic0_.nome_estado) = 'MINAS GERAIS' AND
  (upper(visaoaplic0_.nome_estabelecimento) LIKE '%') AND
  (visaoaplic0_.tipo_estabelecimento IN (1006, 1053, 1148, 1008, 1009, 1007)) AND
  (visaoaplic0_.id_estabelecimento IS NOT NULL)
ORDER BY
    RowNum
;

下次查询的测试数据

DECLARE @Table AS TABLE (Establishment VARCHAR(100), Price MONEY)
INSERT INTO @Table (Establishment, Price)
VALUES ('A',4.5),('B',5.5),('B',3.05),('C',6.75), ('D',NULL), ('C',NULL)

使用公用表表达式的窗口函数如果将null作为第一个价格出现,则处理Null会更好吗?

;WITH cteQuery AS (
    SELECT
       *
       ,RowNumber = ROW_NUMBER() OVER (PARTITION BY Establishment ORDER BY
          IIF(Price IS NULL, 1, 0) ASC
          ,ISNULL(Price,0) ASC)
    FROM
       @Table
)

SELECT
    Establishment
    ,Price
FROM
    cteQuery
WHERE
    RowNumber = 1

其他选项

----Windowed Function with Common Table Expression
;WITH cteQuery AS (
    SELECT
       *
       ,RowNumber = ROW_NUMBER() OVER (PARTITION BY Establishment ORDER BY ISNULL(Price,0) ASC)
    FROM
       @Table
)

SELECT
    Establishment
    ,Price
FROM
    cteQuery
WHERE
    RowNumber = 1


--- Group By with Common Table Expression Method
;WITH cteMin AS (
    SELECT
       Establishment
       ,MinPrice = MIN(ISNULL(Price,0))
    FROM
       @Table
    GROUP BY
       Establishment
)

SELECT
    t.*
FROM
    cteMin m
    INNER JOIN @Table t
    ON m.Establishment = t.Establishment
    AND m.MinPrice = ISNULL(t.Price,0)



-----Group By with Sub Select Method
SELECT
    t.*
FROM
    @Table t
    INNER JOIN (
       SELECT
          Establishment
          ,MinPrice = MIN(ISNULL(Price,0))
       FROM
          @Table
       GROUP BY
          Establishment
    ) g
    ON t.Establishment = g.Establishment
    AND ISNULL(t.Price,0) = g.MinPrice