Group By First Row - sql

SELECT OrderNumber, FIRST(ShippingName) as ShippingName FROM Orders
GROUP BY OrderNumber
This gives an error, how would I do this?

The FIRST function is not supported in SQL Server.
Maybe you want
SELECT OrderNumber, MIN(ShippingName) as ShippingName
FROM Orders
GROUP BY OrderNumber
But, probably not. Instead I suspect you mean... for each OrderNumber, of all the rows with that OrderNumber, select the ShippingName of the first row according to some ordering.
SELECT OrderNumber,
(
SELECT TOP 1 ShippingName
FROM Orders AS OrdersInner
WHERE OrdersInner.OrderNumber = Orders.OrderNumber
ORDER BY OrdersInner.OrderDate, OrdersInner.OrderId
) as ShippingName
FROM Orders
GROUP BY OrderNumber
But I'm making some assumptions about both your requirements and your database structure.

You maybe mean :
SELECT TOP 1 OrderNumber, ShippingName
FROM Orders
ORDER BY OrderNumber DESC

Related

Fixing Nested aggregated function

I am trying to display the productid for the product that has been sold the most (i.e, that has been sold in the highest quantity)
I have tried multiple different versions of code but every time it says cannot nest aggregated operations
SELECT productid
FROM soldvia
GROUP BY productid
WHERE productid IN (SELECT MAX(SUM(noofitems)) FROM soldvia GROUP BY productid);
I expect the output to be
PRODUCTID
3x3
4x4
You can't nest aggregations.
Use ORDER BY with TOP :
SELECT TOP 1 productid
FROM soldvia
GROUP BY productid
ORDER BY SUM(noofitems) DESC
Please try below query for your exact answer.
select productid, sum(noofitems) as max_sold,
convert(varchar,productid) +' x '+ convert(varchar,sum(noofitems)) as
output_sold from soldvia group by productid order by sum(noofitems) desc
Output will be
ProductId NoOfItemSold Output_Sold
1 7 1x7
2 4 2x4
3 1 3x1
In Teradata, you can use the qualify clause:
SELECT productid
FROM soldvia
GROUP BY productid
QUALIFY ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) = 1;
This is handy. You can get duplicates by changing ROW_NUMBER() to RANK(). Actually, RANK() is more consistent with the code in your question.
The answer by #forpas is probably the way to go but this one is a little closer to yours:
SELECT productid
FROM soldvia
GROUP BY productid
HAVING SUM(noofitems) = (
SELECT MAX(items)
FROM (
SELECT SUM(noofitems) AS items
FROM soldvia
GROUP BY productid
) x
)

Filter out only latest entries, for Orders

I'm trying to write a query where i select the latest changes on a specific Order in an OrderTable
ex.
OrderID| ChangeDate |
-------|-----------------------|
Order1 |2013-03-17 14:40:47.000|
Order2 |2013-03-12 12:34:09.000|
Order3 |2013-03-20 18:30:12.000|
Order1 |2013-03-20 16:09:09.000|
Order2 |2013-03-20 12:39:49.000|
Say (from the Example above), what i need is the latest entries of Order1,Order2 and Order3.
Has anyone been in a similar situation?
I am really greatefull for your help!
Try this:
Select OrderID,max(ChangeDate) as LatestDate
from yourTable
group by OrderID
You can simply do this:
SELECT OrderID,
MAX(ChangeDate) as LatestEntry
FROM yourTable
GROUP BY OrderID
There are multiple approaches but assuming you want the whole record and not just the max( date) per order id you can use row_number.
WITH CTE
(
SELECT
OrderID,
changeDate,
ChangeValue,
ROW_NUMBER() OVer (Partition BY OrderID order by ChangeDate Desc) rn
FROM order
)
SELECT * FROM CTE where rn = 1
Note: This returns exactly one record per order. This may or may not be an issue if you have a tie for max change date

SQL GROUP BY on a sub query

I have a query that will return results from 2 tables into 1 using a UNION ALL, which all works as I need it to. However I need to run a GROUP BY and an ORDER BY on the returned dataset however I am getting many errors and I'm not sure how to solve it.
Here is my Query:
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
This will return a results set such as this:
ProductID Quantity
15 2
20 2
15 1
8 5
5 1
I then want to run a GROUP BY on the ProductID field and then finally an ORDER BY DESC on the Quantity field. So in the final output, this particular results set will finally result in this:
ProductID
8
15
20
5
I can then run queries on this result set as I usually do
EDIT:
As stated above, but maybe not implied enough is that I will need to run queries on the returned results, which isn't working as you cannot run a query on a set of results that have an ORDER BY clause (so far as I gathered from the error list)
If you want more information on the problem, here it is:
From this results set, I want to get the products from the product table that they relate to
SELECT * FROM Products WHERE ID IN (
SELECT ProductID
FROM
(
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
) v
GROUP BY ProductID
ORDER BY SUM(Quantity) DESC
)
However, I get this error: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
The output of products need to be in the order that they are returned in the sub query (By quantity)
SELECT Products.*
FROM Products
INNER JOIN
(
SELECT ProductID, Sum(Quantity) as QuantitySum
from
(
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
) v
GROUP BY ProductID
) ProductTotals
ON Products.ID = ProductTotals.ProductID
ORDER BY QuantitySum DESC
will this work?
SELECT ProductID
from
(
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
) temp
GROUP BY temp.ProductID
ORDER BY SUM(temp.Quantity) desc
Here's a cte version (no live test so please excuse blunders)
EDIT
;WITH myInitialdata_cte(ProductID,Quantity)
AS
(
SELECT ProductID, Quantity FROM BasketItems
UNION ALL
SELECT ProductID, Quantity FROM OrderItems
)
SELECT b.ID
FROM
myInitialdata_cte a
INNER JOIN Products b ON
a.ProductID = b.ID
GROUP BY ProductID
ORDER BY SUM(a.Quantity) DESC

Sql query to select records for a single distinct customer id

I have written a query for sales by customers in groups it is as follows:
SELECT customerid,
SUM (salestax1)As total_salestax1,
SUM(total_payment_received) As total_payment_recieved,
COUNT (orderid)as order_qty,
SUM(paymentamount)As paymentamount
FROM Orders_74V94W6D22$
WHERE orderdate between '7/6/2011 16:35' and '2/3/2012 11:53'
GROUP BY customerid
but this query shows only 5 fields but I need to show following fields:
orderid billingcompanyname billingfirstname billinglastname
billingcountry shipcountry paymentamount creditcardtransactionid
orderdate creditcardauthorizationdate orderstatus
total_payment_received tax1_title salestax1
then how to deal with it?
you need to understand what GROUP BY means.
If you are grouping by customerId, you will have only one customer because all data is grouped into it.
How do you want to group by orderid and display the orderid on your result set? If you have 10 order ids, do you expect 10 rows on the result? If yes, fine, group by it but I don't think that's what you want
EDIT:
Well, this is NOT a good idea, your table structure is WRONG and I dont think you fully understand that a group by means, BUT I think this query will get your result:
SELECT customerid,
(select top 1 [column1] from Orders_74V94W6D22$ where customerid = ORD.customerid),
(select top 1 [column2] from Orders_74V94W6D22$ where customerid = ORD.customerid),
(select top 1 [column3] from Orders_74V94W6D22$ where customerid = ORD.customerid),
SUM (salestax1)As total_salestax1,
SUM(total_payment_received) As total_payment_recieved,
COUNT (orderid)as order_qty,
SUM(paymentamount)As paymentamount
FROM Orders_74V94W6D22$ ORD
WHERE orderdate between '7/6/2011 16:35' and '2/3/2012 11:53'
GROUP BY customerid
To select more about the customer, you need to use your query as a sub query, something like:
Select distinct c.[column1], c.[column2], c.[column3], tbl.*
From Orders_74V94W6D22$ c inner join (
SELECT customerid,
SUM (salestax1)As total_salestax1,
SUM(total_payment_received) As total_payment_recieved,
COUNT (orderid)as order_qty,
SUM(paymentamount)As paymentamount
FROM Orders_74V94W6D22$
WHERE orderdate between '7/6/2011 16:35' and '2/3/2012 11:53'
GROUP BY customerid
) as tbl on tbl.customerid = c.customerid
but you cant logically select something about 1 order as youve grouped multiple orders

SQL question about GROUP BY

I've been using SQL for a few years, and this type of problem comes up here and there, and I haven't found an answer. But perhaps I've been looking in the wrong places - I'm not really sure what to call it.
For the sake of brevity, let's say I have a table with 3 columns: Customer, Order_Amount, Order_Date. Each customer may have multiple orders, with one row for each order with the amount and date.
My Question: Is there a simple way in SQL to get the DATE of the maximum order per customer?
I can get the amount of the maximum order for each customer (and which customer made it) by doing something like:
SELECT Customer, MAX(Order_Amount) FROM orders GROUP BY Customer;
But I also want to get the date of the max order, which I haven't figured out a way to easily get. I would have thought that this would be a common type of question for a database, and would therefore be easy to do in SQL, but I haven't found an easy way to do it yet. Once I add Order_Date to the list of columns to select, I need to add it to the Group By clause, which I don't think will give me what I want.
Apart from self-join you can do:
SELECT o1.*
FROM orders o1 JOIN orders o2 ON o1.Customer = o2.Customer
GROUP BY o1.Customer, o1.Order_Amount
HAVING o1.Order_Amount = MAX(o2.Order_Amount);
There's a good article reviewing various approaches.
And in Oracle, db2, Sybase, SQL Server 2005+ you would use RANK() OVER.
SELECT * FROM (
SELECT *
RANK() OVER (PARTITION BY Customer ORDER BY Order_Amount DESC) r
FROM orders) o
WHERE r = 1;
Note: If Customer has more than one order with maximum Order_Amount (i.e. ties), using RANK() function would get you all such orders; to get only first one, replace RANK() with ROW_NUMBER().
There's no short-cut... the easiest way is probably to join to a sub-query:
SELECT
*
FROM
orders JOIN
(
SELECT Customer, MAX(Order_Amount) AS Max_Order_Amount
FROM orders
GROUP BY Customer
) maxOrder
ON maxOrder.Customer = orders.Customer
AND maxOrder.Max_Order_Amount = orders.Order_Amount
you will want to join on the same table...
SELECT Customer, order_date, amt
FROM orders o,
( SELECT Customer, MAX(Order_Amount) amt FROM orders GROUP BY Customer ) o2
WHERE o.customer = o2.customer
AND o.order_amount = o2.amt
;
Another approach for the collection:
WITH tempquery AS
(
SELECT
Customer
,Order_Amount
,Order_Date
,row_number() OVER (PARTITION BY Customer ORDER BY Order_Amount DESC) AS rn
FROM
orders
)
SELECT
Customer
,Order_Amount
,Order_Date
FROM
tempquery
WHERE
rn = 1
If your DB Supports CROSS APPLY you can do this as well, but it doesn't handle ties correctly
SELECT [....]
FROM Customer c
CROSS APPLY
(SELECT TOP 1 [...]
FROM Orders o
WHERE c.customerID = o.CustomerID
ORDER BY o.Order_Amount DESC) o
See this data.SE query
You could try something like this:
SELECT Customer, MAX(Order_Amount), Order_Date
FROM orders O
WHERE ORDER_AMOUNT = (SELECT MAX(ORDER_AMOUNT) FROM orders WHERE CUSTOMER = O.CUSTOMER)
GROUP BY CUSTOMER, Order_Date
with t as
(
select CUSTOMER,Order_Date ,Order_Amount,max(Order_Amount) over (partition
by Customer) as
max_amount from orders
)
select * from t where t.Order_Amount=max_amount