Add row to SQL query results with totals of certain columns - sql

I have a sql query
select * from orderTable
that returns:
I want to have the query return an additional row that has orderId = 'Total' and the sum of GrossAmt, Payments, NetAmt with the remaining fields being empty, like this:
What I've tried:
select isnull(OrderId, 'Total') as OrderId, GrossAmt
from (
select OrderId, SUM(GrossAmt) as GrossAmt
from orderTable
group by OrderId with rollup
) as OT
Which will return the last row with Total and sum of GrossAmt, but when I try to add, say StoreId like:
select isnull(OrderId, 'Total') as OrderId, GrossAmt, StoreId
from (
select OrderId, SUM(GrossAmt) as GrossAmt, StoreId
from orderTable
group by OrderId, StoreId with rollup
) as OT
Then I get double the results with a duplicate for each row only with a null value for StoreId.
I just had the idea to switch the place of OrderId and StoreId in the above query and that has given me my closest results. I have exactly what I want, only there are 2 total rows at the bottom, one with a null StoreId.

You can use UNION to make it a single table:
select * from
(
select cast(OrderId as Varchar) as OrderId, Custname, GrossAmt, Payments, NetAmt, StoreId, StaffName
from orderTable
UNION
(select 'Total' as OrderId, Null as Custname,
Sum(GrossAmt) As GrossAmt,
Sum(Payments) As Payments,
Sum(NetAmt) As NetAmt, Null as StoreId, Null as StaffName
from orderTable)
) a
Notice the cast to have the word Total fit in the OrderId column

SELECT ISNULL(OrderId, 'Total') as OrderId, GrossAmt, NULL AS storeId
FROM (
SELECT OrderId, SUM(GrossAmt) as GrossAmt
FROM orderTable
GROUP BY
OrderId WITH ROLLUP
) AS OT

Related

SQL-select two values that are the same in different rows but still be able to see a third value

i have three columns orderdate, customerid and productid. i only want to see the rows where orderdate and customerid is repeated. so when the customer orders something on the same day. but i also want to see the product id.
SELECT orderdate, customerid, productid
FROM sales_orders_sheet
GROUP BY orderdate, customerid
HAVING COUNT(*)>1
when I use this sql statement I get;
Field of aggregated query neither grouped nor aggregated: line 1, column 31
You can do:
select *
from (
select t.*, count(1) over(partition by orderdate, customerid) as cnt
from sales_orders_sheet t
) x
where cnt > 1

Can you combine 3 CTE's into one?

I have a query written with 3 CTE's and I need to get the exact same result using only 1 CTE. Can someone help me?
WITH Q1(cid, sumEP) AS
(
SELECT customerid, SUM(Extendedprice)
From "Invoices"
GROUP BY customerid
), Q2(cid, oid, mf) AS
(
SELECT DISTINCT customerid, orderid, freight
FROM "Invoices"
), Q3 AS
(
SELECT cid, SUM(mf) AS smf
FROM Q2
GROUP BY cid
)
SELECT Q1.cid, sumEP + smf AS total
FROM Q1
JOIN Q3 ON Q1.cid = Q3.cid
LIMIT 10
smf is the sum of distinct values of freight per order (for the same customer), but this you can do with sum(distinct freight)
So I would suggest this query:
WITH Q(customerid, orderid, total) AS
(
SELECT customerid, orderid, SUM(Extendedprice) + SUM(DISTINCT freight)
FROM Invoices
GROUP BY customerid, orderid
)
SELECT customerid, SUM(total) AS total
FROM Q
GROUP BY customerid
ORDER BY 2 DESC
LIMIT 10;
When there are no cases where different orders for the same customer have the same freight value, then it can be simplified to:
SELECT customerid, SUM(Extendedprice) + SUM(DISTINCT freight) AS total
FROM Invoices
GROUP BY customerid
ORDER BY 2 DESC
LIMIT 10
Note I added an order by so that you limit the results with some logic behind it -- in this case getting the top-10 by total. Change as needed.

Use CTE and UNION ALL with SQL Server 2014

My problem is that:
Create a view that shows the top 5 selling products as well as an aggregated row that shows the total sales for all other products and a Grand total row that sums all of the above.
WITH ProductTop5 AS
(
SELECT [dbo].[Product].[ProductName] AS ProductName, SUM([dbo].[SalesOrderDetail].[LineTotal]) AS TotalAmount
FROM [dbo].[Product]
JOIN [dbo].[SalesOrderDetail] ON [dbo].[Product].[ProductID] = [dbo].[SalesOrderDetail].[ProductID]
GROUP BY [dbo].[Product].[ProductName]
)
You could use ROW_NUMBER/RANK to calculate ranking of product:
WITH Product AS
(
SELECT p.[ProductName] AS ProductName,
SUM(sod.[LineTotal]) AS TotalAmount
FROM [dbo].[Product] p
JOIN [dbo].[SalesOrderDetail] sod
ON p.[ProductID] = sod.[ProductID]
GROUP BY p.[ProductName]
), ProductWithRank AS (
SELECT ProductName, Total_Amount,
ROW_NUMBER() OVER(ORDER BY Total_Amount DESC) AS rn
FROM Product
)
SELECT ProductName, TotalAmount
FROM ProductWithRank
WHERE rn <= 5
UNION ALL
SELECT 'All Others', SUM(Total_Amount)
FROM ProductWithRank
WHERE rn > 5
UNION ALL
SELECT 'Grand Total', SUM(TotalAmount)
FROM ProductWithRank;

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

Dedupe records without DELETE

I need to bring back only one of the records from a duplicated row in SQL Server
I have data like this
-------------------------------------------
CustomerID, OrderID, ProductID, Title
-------------------------------------------
1,1001,131,orange
1,1002,131,orange
-------------------------------------------
These rows are shown as 2 items that have been ordered by the same person, really they are just two as the quantity chosen in the basket and 2 records.
My question is how can i retrieve only one of these rows?
Thanks
Maybe something like this:
First some test data:
DECLARE #tbl TABLE(CustomerID INT,OrderID INT,ProductID INT,Title VARCHAR(100))
INSERT INTO #tbl
VALUES
(1,1001,131,'orange'),
(1,1002,131,'orange')
Then the query
;WITH CTE AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY tbl.CustomerID,tbl.ProductID,tbl.Title
ORDER BY tbl.OrderID) AS RowNbr,
tbl.CustomerID,
tbl.OrderID,
tbl.ProductID,
tbl.Title
FROM
#tbl AS tbl
)
SELECT
*
FROM
CTE
WHERE
CTE.RowNbr=1
This way you can get, not only one of both rows, but also the quantity ordered
SELECT
CustomerID, ProductID, Title, max(OrderID) as orderID, COUNT(*) as quantity
FROM
TableName
GROUP BY
CustomerID,
ProductID,
Title
Using Max will get you the most recent order
SELECT CustomerID, MAX(OrderId), ProductID, Title
FROM table
GROUP BY CustomerID, ProductID, Title
OR
Using Min will get you the first order
SELECT CustomerID, MIN(OrderId), ProductID, Title
FROM table
GROUP BY CustomerID, ProductID, Title
Provided that it's really what you want you can get the first order of each order with the same customer, product and title using a grouping and the MIN function (MAX would give you the last order):
SELECT CustomerID, MIN(OrderID) AS OrderID, ProductID, Title
FROM MyTable
GROUP BY CustomerID, ProductID, Title
If you want the number of duplicate orders (that would be the ordered quantity judging by your question) you can add a count:
SELECT CustomerID, MIN(OrderID) AS OrderID, ProductID, Title,
COUNT(*) AS Quantity
FROM MyTable
GROUP BY CustomerID, ProductID, Title