Hide column in sql query output - sql

SELECT
MProduct.ProductCode, MProduct.ProductName, COUNT(*) AS Ranges
FROM
TProblem
FULL OUTER JOIN
MProduct ON TProblem.ProductCode = MProduct.ProductCode
GROUP BY
MProduct.ProductCode, MProduct.ProductName
ORDER BY
Ranges DESC
This is my query but I want to hide the Ranges column from output

To maintain the order of your results, just move the count from your select to the order by:
SELECT
MProduct.ProductCode, MProduct.ProductName
FROM
TProblem
FULL OUTER JOIN
MProduct ON TProblem.ProductCode = MProduct.ProductCode
GROUP BY
MProduct.ProductCode, MProduct.ProductName
ORDER BY
count(*) DESC

I understand where #marc_s is coming from. It looks like you are trying to get a list of DISTINCT rows
SELECT ProductCode, ProductName
FROM
(
SELECT TOP 100 PERCENT
MProduct.ProductCode, MProduct.ProductName, COUNT(*) AS Ranges
FROM
TProblem
FULL OUTER JOIN
MProduct ON TProblem.ProductCode = MProduct.ProductCode
GROUP BY
MProduct.ProductCode, MProduct.ProductName
ORDER BY
Ranges DESC
) AS DATA
Or alternatively
SELECT DISTINCT
MProduct.ProductCode, MProduct.ProductName
FROM
TProblem
FULL OUTER JOIN
MProduct ON TProblem.ProductCode = MProduct.ProductCode
MProduct.ProductCode, MProduct.ProductName

Related

Column "not contained in either an aggregate function or a GROUP BY clause"

The query:
SELECT
A.mrno, A.remarks,
B.itemcode, B.description, B.uom, B.quantity,
C.whsecode, MAX(C.quantity) AS whseqty, D.rate
FROM
Mrhdr A
INNER JOIN
Mrdtls B ON A.mrno = B.mrno
INNER JOIN
inventoryTable C ON B.itemcode = C.itemcode
INNER JOIN
Items D ON B.itemcode = D.itemcode
WHERE
(A.mrno = #MRNo AND B.quantity < C.quantity);
The error:
Column 'Mrhdr.mrno' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
It says that the column mrno is not contained in the aggregate function of something, but when I do something about it like put it in a GROUP BY clause, the next column requests return the same error until the last column except the C.quantity column, and when they are all in a GROUP BY clause it will only return the same output not returning the highest or maximum value for the quantity. What should I do with the other columns when I use MAX or aggregate functions.
The output of the query above:
If I put all of the columns in a GROUP BY clause it returns an output with two of the itemcode FG 4751, it just removes the error of aggregate function, but I just want the highest value to be returned (just the 100, the highest quantity in the warehouse/inventory).
You want to deal with the maximum inventory quantity per product. But you are joining all inventory rows, where you should only pick the maximum quantity rows.
This can be done with a lateral join, if your DBMS supports this (you have forgotton to tell us which you are using) or simply by joining the rows in question by applying a window function as follows.
SELECT
A.mrno, A.remarks,
B.itemcode, B.description, B.uom, B.quantity,
C.whsecode, C.whseqty, D.rate
FROM
Mrhdr A
INNER JOIN
Mrdtls B ON A.mrno = B.mrno
INNER JOIN
(
SELECT
itemcode, whsecode, quantity as whseqty,
MAX(quantity) OVER (PARTITION BY itemcode) AS max_qty
FROM inventoryTable
) C ON B.itemcode = C.itemcode AND C.whseqty = C.max_qty
INNER JOIN
Items D ON B.itemcode = D.itemcode
WHERE
A.mrno = #MRNo AND B.quantity < C.whseqty;
This query should work in most DBMS. If you are working with a DBMS that supports the standard SQL FETCH WITH TIES clause, I'd change the join to:
INNER JOIN
(
SELECT itemcode, whsecode, quantity as whseqty
FROM inventoryTable
ORDER BY RANK() OVER (PARTITION BY itemcode ORDER BY quantity DESC)
FETCH FIRST ROW WITH TIES
) C ON B.itemcode = C.itemcode
so as to only select the top rows inside the subquery already and not to awkwardly filter them later. But well, a lateral join may even be considered more straight-forward here.
The alternative to putting everything in a group by clause would be to use a window function. The question then becomes what is the MAX value relative to?
For example, you could get the MAX value based on all criteria, which would return a similar result to group by without leaving only distinct values for the column.
SELECT
A.mrno,
A.remarks,
B.itemcode,
B.description,
B.uom,
B.quantity,
C.whsecode,
MAX(C.quantity) OVER(PARTITION BY A.mrno, A.remarks, B.itemcode, B.description, B.uom, B.quantity, C.whsecode, D.rate) AS whseqty,
D.rate
FROM
Mrhdr A
INNER JOIN
Mrdtls B ON A.mrno = B.mrno
INNER JOIN
inventoryTable C ON B.itemcode = C.itemcode
INNER JOIN
Items D ON B.itemcode = D.itemcode
WHERE
(A.mrno = #MRNo AND B.quantity < C.quantity);

Getting a SUM of the values in INNER JOIN adds up duplicate values

I am running a query which is counting the records on monthly basis from the table.
I am trying to add one extra column called "TotalPrice", I need a sum of all the prices from 'settle' table.
The problem I am facing is because of INNER JOIN, 'SUM' of the prices is adding up multiple prices due to duplicate records which the INNER JOIN is returning. Is there a way to avoid it and get a SUM of the prices from unique records ?
SELECT
CONCAT(year(datetime), '-', month(datetime)) AS YearMonth,
COUNT (DISTINCT a.id) AS TOTAL, SUM(total_price) AS TotalPrice
FROM settle AS a with (nolock)
INNER JOIN transfers b with (nolock) ON b.settleId = a.id
INNER JOIN Fdata AS c with (nolock) ON c.id= b.data
GROUP BY CONCAT(year(datetime), '-', month(datetime))
Thanks in advance.
sql server 2008 onwards:
with CTE as -- A CTE alows us to manipulate the data before we use it, like a derived table
(
select datetime, id, total_price,
row_number() over(partition by id, datetime order by total_price) as rn -- This creates a row number for each combo of id and datetime that appears
FROM settle AS a with (nolock)
INNER JOIN transfers b with (nolock) ON b.settleId = a.id
INNER JOIN Fdata AS c with (nolock) ON c.id= b.data
)
SELECT CONCAT(year(datetime), '-', month(datetime)) AS YearMonth,
COUNT (DISTINCT a.id) AS TOTAL,
SUM(total_price) AS TotalPrice
from CTE
where rn = 1 -- that row_number we created? This selects only the first one, removing duplicates
group by CONCAT(year(datetime), '-', month(datetime))

Top 10 by Customer - Total

I'm having some issues....how do I get the following code fixed to return the table below as a sum of customers? I want a total of customer quantities by customer, and then a top 10 list. So all of the Yellow Rose should be added together and then counted as one entry, instead of all of their shipments showing up individually.
select top 10 T1.Quantity, T1.CustName
from
(
select
SUM(Tkscale.Qty)Quantity,
Slcust.Name CustName
from Tkscale with (nolock)
left outer join Slcust with (nolock) on Tkscale.CustomerID = Slcust.CustomerID
group by Tkscale.CustomerID, Tkscale.Qty, Slcust.Name
) T1
order by T1.CustName desc, T1.Quantity desc
try to remove in grouping 'Tkscale.Qty'
Remove the Tkscale.Qty from the GROUP BY clause in your inner query. I also think that you want top 10 largest customers by quantity, not by their names:
select top 10 T1.Quantity, T1.CustName
from
(
select
SUM(Tkscale.Qty)Quantity,
Slcust.Name CustName
from Tkscale with (nolock)
left outer join Slcust with (nolock) on Tkscale.CustomerID = Slcust.CustomerID
group by Slcust.Name
) T1
order by T1.Quantity desc, T1.CustName desc
^ change the sequence of the ORDER BY clause

How to have SQL INNER JOIN accept null results

I have the following query:
SELECT TOP 25 CLIENT_ID_MD5, COUNT(CLIENT_ID_MD5) TOTAL
FROM dbo.amazonlogs
GROUP BY CLIENT_ID_MD5
ORDER BY COUNT(*) DESC;
Which returns:
283fe255cbc25c804eb0c05f84ee5d52 864458
879100cf8aa8b993a8c53f0137a3a176 126122
06c181de7f35ee039fec84579e82883d 88719
69ffb6c6fd5f52de0d5535ce56286671 68863
703441aa63c0ac1f39fe9e4a4cc8239a 47434
3fd023e7b2047e78c6742e2fc5b66fce 45350
a8b72ca65ba2440e8e4028a832ec2160 39524
...
I want to retrieve the corresponding client name (FIRM) using the returned MD5 from this query, so a row might look like:
879100cf8aa8b993a8c53f0137a3a176 126122 Burger King
So I made this query:
SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL, c.FIRM
FROM dbo.amazonlogs a
INNER JOIN dbo.customers c
ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY a.CLIENT_ID_MD5, c.FIRM
ORDER BY COUNT(*) DESC;
This returns something like:
879100cf8aa8b993a8c53f0137a3a176 126122 Burger King
06c181de7f35ee039fec84579e82883d 88719 McDonalds
703441aa63c0ac1f39fe9e4a4cc8239a 47434 Wendy's
3fd023e7b2047e78c6742e2fc5b66fce 45350 Tim Horton's
Which works, except I need to return an empty value for c.FIRM if there is no corresponding FIRM for a given MD5. For example:
879100cf8aa8b993a8c53f0137a3a176 126122 Burger King
06c181de7f35ee039fec84579e82883d 88719 McDonalds
69ffb6c6fd5f52de0d5535ce56286671 68863
703441aa63c0ac1f39fe9e4a4cc8239a 47434 Wendy's
3fd023e7b2047e78c6742e2fc5b66fce 45350 Tim Horton's
How should I modify the query to still return a row even if there is no corresponding c.FIRM?
Replace INNER JOIN with LEFT JOIN
use LEFT JOIN instead of INNER JOIN
Instead of doing an INNER join, you should do a LEFT OUTER join:
SELECT
a.CLIENT_ID_MD5,
COUNT(a.CLIENT_ID_MD5) TOTAL,
ISNULL(c.FIRM,'')
FROM
dbo.amazonlogs a LEFT OUTER JOIN
dbo.customers c ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY
a.CLIENT_ID_MD5,
c.FIRM
ORDER BY COUNT(0) DESC
http://www.w3schools.com/sql/sql_join.asp
An inner join excludes NULLs; you want a LEFT OUTER join.
SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL, IsNull(c.FIRM, 'Unknown') as Firm
FROM dbo.amazonlogs a
LEFT JOIN dbo.customers c ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY a.CLIENT_ID_MD5, c.FIRM ORDER BY COUNT(*) DESC;
This will give you a value of "Unknown" when records in the customers table don't exist. You could obviously drop that part and just return c.FIRM if you want to have actual nulls instead.
Change your INNER JOIN to an OUTER JOIN...
SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL, c.FIRM
FROM dbo.amazonlogs a
LEFT OUTER JOIN dbo.customers c
ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY a.CLIENT_ID_MD5, c.FIRM
ORDER BY COUNT(*) DESC;
WITH amazonlogs_Tallies
AS
(
SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL
FROM dbo.amazonlogs a
GROUP
BY a.CLIENT_ID_MD5
),
amazonlogs_Tallies_Firms
AS
(
SELECT a.CLIENT_ID_MD5, a.TOTAL, c.FIRM
FROM amazonlogs_Tallies a
INNER JOIN dbo.customers c
ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
)
SELECT CLIENT_ID_MD5, TOTAL, FIRM
FROM amazonlogs_Tallies_Firms
UNION
SELECT CLIENT_ID_MD5, TOTAL, '{{NOT_KNOWN}}'
FROM amazonlogs_Tallies
EXCEPT
SELECT CLIENT_ID_MD5, TOTAL, '{{NOT_KNOWN}}'
FROM amazonlogs_Tallies_Firms;

How do I join this sql query to another table?

I have the following SQL query and so far it works the way it should and gets the top 40 tag ids that I have stored in the tagmap table.
SELECT TOP 40
tbrm_TagMap.TagID,
Count(*)
FROM tbrm_TagMap
GROUP BY tbrm_TagMap.TagID
ORDER BY COUNT(tbrm_TagMap.TagID) DESC
I also want to join to the Tags table which contains the actual name of each TagID. Each attempt I make comes back with an error. How can I achieve this? I am using SQL 2008.
SELECT *
FROM (
SELECT TOP 40
tbrm_TagMap.TagID, COUNT(*) AS cnt
FROM tbrm_TagMap
GROUP BY
tbrm_TagMap.TagID
ORDER BY
COUNT(*) DESC
) q
JOIN Tags
ON Tags.id = q.TagID
ORDER BY
cnt DESC
My guess is that when you were joining tags, you weren't including it in the group by clause, which will always through an error in SQL Server. Every column not aggregated but returned needs to be in the group by.
Try something like this:
SELECT TOP 40
tbrm_TagMap.TagID,
t.Tag,
Count(*)
FROM
tbrm_TagMap
INNER JOIN tags t ON
tbrm_TagMap.TagID = t.TagID
GROUP BY
tbrm_TagMap.TagID,
t.Tag
ORDER BY 3 DESC
SELECT TOP 40
tbrm_TagMap.TagID, Tags.TagName Count(*)
FROM tbrm_TagMap INNER JOIN Tags ON tbrm_TagMap.TagID = Tags.TagID
GROUP BY tbrm_TagMap.TagID, Tags.TagName
ORDER BY COUNT(tbrm_TagMap.TagID) DESC
Try this..
SELECT top 40 tags.TagDescription, tbrm_TagMap.TagID, Count(*)
FROM tbrm_TagMap
INNER JOIN Tags
ON TagMap.TagID = Tags.TagId
GROUP BY tags.TagDescription, tbrm_TagMap.TagID
ORDER BY COUNT(tbrm_TagMap.TagID) DESC