Select multiple columns from a table, but group by one

后端 未结 11 1451
逝去的感伤
逝去的感伤 2020-12-12 14:54

The table name is \"OrderDetails\" and columns are given below:

OrderDetailID || ProductID || ProductName || OrderQuantity

I\'m trying to s

11条回答
  •  孤街浪徒
    2020-12-12 15:27

    In my opinion this is a serious language flaw that puts SQL light years behind other languages. This is my incredibly hacky workaround. It is a total kludge but it always works.

    Before I do I want to draw attention to @Peter Mortensen's answer, which in my opinion is the correct answer. The only reason I do the below instead is because most implementations of SQL have incredibly slow join operations and force you to break "don't repeat yourself". I need my queries to populate fast.

    Also this is an old way of doing things. STRING_AGG and STRING_SPLIT are a lot cleaner. Again I do it this way because it always works.

    -- remember Substring is 1 indexed, not 0 indexed
    SELECT ProductId
      , SUBSTRING (
          MAX(enc.pnameANDoq), 1, CHARINDEX(';', MAX(enc.pnameANDoq)) - 1
        ) AS ProductName
      , SUM ( CAST ( SUBSTRING (
          MAX(enc.pnameAndoq), CHARINDEX(';', MAX(enc.pnameANDoq)) + 1, 9999
        ) AS INT ) ) AS OrderQuantity
    FROM (
        SELECT CONCAT (ProductName, ';', CAST(OrderQuantity AS VARCHAR(10)))
          AS pnameANDoq, ProductID
        FROM OrderDetails
      ) enc
    GROUP BY ProductId
    

    Or in plain language :

    • Glue everything except one field together into a string with a delimeter you know won't be used
    • Use substring to extract the data after it's grouped

    Performance wise I have always had superior performance using strings over things like, say, bigints. At least with microsoft and oracle substring is a fast operation.

    This avoids the problems you run into when you use MAX() where when you use MAX() on multiple fields they no longer agree and come from different rows. In this case your data is guaranteed to be glued together exactly the way you asked it to be.

    To access a 3rd or 4th field, you'll need nested substrings, "after the first semicolon look for a 2nd". This is why STRING_SPLIT is better if it is available.

    Note : While outside the scope of your question this is especially useful when you are in the opposite situation and you're grouping on a combined key, but don't want every possible permutation displayed, that is you want to expose 'foo' and 'bar' as a combined key but want to group by 'foo'

提交回复
热议问题