Choose an aggregate function for Group BY in SQL Server - sql-server

I have a query like this:
Select Count(*) as TotalCount, Object2_ID, Object_ID, Object_Description
from Table1
inner join table2 on...
Group BY Object2_ID, Object_ID
I can't run this query because the column Object_Description isn't in GROUP BY or under aggregate function. Object_Description is a text column. I need any value of Object_Description. Now I use MAX(Object_Description) because it gives me right results, because Object_Description is the same for each group.
I can use MAX() or MIN() etc. - I will get right results in my query.
The question is - what is the most sufficient way to do this ?
I think that MAX() or MIN() produces small overheads.

You can get Object Description later, after calculation quantity (assumed that description in in table1 and you need get count from Table2):
SELECT Object_Id, Object_Description, Qty
FROM
(
SELECT Object_Id, Count(*) Qty
FROM Table2
GROUP BY Object_Id
) t
JOIN Table1 t2 on t2.Object_Id = t.Object_Id

Related

Does NOT EXIST (in the absense of where clause in the subquery) implicitly assume that where clause is on column selected by subquery?

Link: https://blog.udemy.com/sql-not-exists/
select * from customers
where NOT EXISTS (
select customerID from orders)
I had always thought that the subquery should be written such that the subquery table (orders) should have a where clause to lookup the value from the outer table (customers).
However above example seems to be without where clause in the subquery.
For example I would have written it like this:
select * from customers c
where NOT EXISTS (
select 1 from orders o
where c.customerID=o.customerID)
So does the subquery implicitly consider where clause to be on customerID in the 1st example?
The queries do different things. The first one, returns record if specific condition is true. It's like the followings:
select * from customers
where 1 = 0
select * from customers
where 1 = 1
In such cases, the condition is not referring the data in the specified table. You can use this, for example, to return or not return rows based on specific input parameter.
In your case, I expect that the NOT EXISTS ( select customerID from orders) will always be false, as orders exists, so no data is returned.
The second query is doing what you actually want - return customers that do not have any orders. I prefer using LEFT JOINs for such queries. In AdventureWorks2012 it will look like:
select count(*)
from Production.Product
where NOT EXISTS (
select ProductID from Sales.SalesOrderDetail)
select count(*)
from Production.Product c
where NOT EXISTS (
select 1 from Sales.SalesOrderDetail o
where c.ProductID=o.ProductID)
SELECT count(*)
from Production.Product c
LEFT JOIN Sales.SalesOrderDetail o
ON c.ProductID=o.ProductID
WHERE o.ProductID IS NULL

Keeping the results with GROUP BY

I connect four tables, but if I do a GROUP BY with a propertie of the fourth table, I get different results. This is the Query:
There are basically two options:
JOIN back to original table using nested query.
SELECT TA.col1, AggrFunc(col2) AS col2,
(SELECT col3 -- TOP 1? MAX? It must be single row
FROM table1 AS TB
JOIN TA ON TA. = TB. -- INNER JOIN? LEFT OUTER JOIN?
FROM table1 AS TB JOIN table2 JOIN table3
GROUP BY TA.col1;
Or use a CTE. You have more control on how many rows of extra columns to return
WITH CTE AS
(
SELECT col1, AggrFunc(col2) AS col2
FROM ... JOINs
GROUP BY col1
)
SELECT CTE.*, table1.col3
FROM CTE
JOIN table1 --INNER JOIN? LEFT OUTER JOIN?
Use window function if possible
SELECT col1, AggrFunc(col2) OVER (PARTITION BY col1) AS col2, extra_col3
FROM ...JOINs...
then you can put above query a CTE or FROM clause to further filtering or grouping.
SELECT
FROM (query above)
WHERE ...
GROUP BY ...
The question is same: How do you get single extra_col3(SKU.[Reorder Cycle] in your case) row? How do you pick up one record when there are multiple matches to your grouped data.
Oke, this was doing the job(oke, I made a pivot of it):

Grouping data based on expression using CountDistinct aggregate function

I am newbie to Stack overflow and also SQL server reporting services. So please excuse me for the format of the question.
So here is the situation:
I am developing a SSRS report which needs to be grouped by an Count of Distinct product names as shown below.
I created a text box called ProdCount with an expression
COUNTDISTNCT(Fields!Product.value,"DataSet1")
which gives me the count 63 within the scope of DataSet1.
Now i need to group the data by taking product names where the above formula is >1 .
=IIF(ProdCount>1,Fields!Product.value,Nothing)
My Problem:
I tried to call the ProdCount from the calculated field since i
cant use the aggregate functions in Calculated Fields and use
the second expression by using
= ReportItems!ProdCount.value
which gives me an error FieldValue Denying ReportItems
I tried to combine the above two expressions by creating a calculated field by
IIF(CountDistinct(Fields!Product.Value,"DataSet1")>1,Fields!Product.Value,Nothing)
which gives me an error Calculated fields cannot have expressions
I tried to use Report Variables in the same way as above(1) which was not working either.
I also tried to use CROSS JOIN in the query
Select Count(Distinct(Product Name)
from Query1
Cross join
My Main Query which give me the data
which is taking more time to execute.
So Can anyone help me with solution where i can group the data by combining the above two expressions.
Please excuse me for the format. I was confused with framing question. I accept all your edits , so that i can learn in future.
Here is my code:
SELECT * FROM
--Query1 which counts the number of distinct products)
(SELECT DISTINCT COUNT(gproduct.ProductName) AS ProdCount
FROM Table1
LEFT JOIN Table4
ON Table1.column=Table1.column
LEFT JOIN Table2
ON Table3.Column = TTable1.Column
LEFT JOIN
(
SELECT Distinct Table6.Name AS ProductName,Table9.ColumnId
FROM Table6
INNER JOIN Table7
ON Table6.Column=Table7.Column
INNER JOIN Table8
ON Table7.Column=Table8.Column
INNER JOIN Table9
ON Table9.Column=Table8.Column
)gproduct
ON Table1.ColumnId=gproduct.ColumnId
GROUP BY gproduct.ColumnId,
)qProduct
CROSS JOIN
--My main Query which get data from different table including Product name
(SELECT
Upper(CASE WHEN (CASE WHEN Table4.Column =1 THEN 'Yes' ELSE 'NO' END)='YES'
THEN gab.ProductName
ELSE
Table2.productName
END) AS Product,
FROM Table1 AS ec
LEFT JOIN Table2 AS ep
ON --
LEFT JOIN Table3 AS ebrd
ON --
Left JOIN Table4 AS etpc
ON --
LEFT JOIN Table5 AS gst
ON --
LEFT JOIN
(
SELECT Distinct Table6.Name AS ProductName,Table9.ColumnId
FROM Table6
INNER JOIN Table7
ON Table6.Column=Table7.Column
INNER JOIN Table8
ON Table7.Column=Table8.Column
INNER JOIN Table9
ON Table9.Column=Table8.Column
) gab
ON Table1.ColumnId=gab.ColumnId
)QMain
Personally I would try to solve the problem in query itself instead of SSRS report. According the data you provided it would be something like:
SELECT
ProductName,
count(distinct Product)
from
YourTable
group by
ProductName
having count(distinct product) > 1
Later on creating SSRS report should be quite easy.

Small ms Sql query to get the max of an id with some criteria

I want sql query to get the above result. The result is the maximum Id in TableA whose s_id in TableB has Stat=true i.e. 1.
The following does not do what I want:
select i.category_id,i.image_id,i.image_original,i.image_title,i.photographer
from images i
inner join schedule s
on i.scheduleid=s.scheduleid
and s.status='live'
where image_id=(select max(image_id) from images)
Use TOP to retrieve only 1 row
Use ORDER BY to control the sorting, so you get the single row you want
SELECT TOP(1) a.id, a.[image], a.s_id, b.stat, b.[desc]
FROM TableA a
JOIN TableB b on a.s_id = b.s_id
WHERE b.stat = 1
ORDER BY A.ID DESC
An SQLFiddle showing this.

Updating column with value from other table, can't use distinct function

My original data is in Table2. I created Table1 from scratch. I populated Column A like this:
INSERT INTO Table1("item")
SELECT DISTINCT(Table2."item")
FROM Table2
I populated Table1.Totals (Column B) like this:
UPDATE Table1
SET totals = t2.q
FROM Table1 INNER JOIN
(
SELECT t2."item"
, SUM(t2.quantity) AS q
FROM t2
GROUP BY t2."item"
) AS t2
ON Table1."item" = t2."item"
How can I populate Table1."date"? My UPDATE above doesn't work here because I can't use an aggregate function on a date. I was able to get the results I wanted using the following code in a separate query:
SELECT DISTINCT Table1."item"
, Table2."date"
FROM Table1 INNER JOIN Table2
ON Table1."item" = Table2."item"
ORDER BY Table1."item"
But how do I use the results of this query to SET the value of the column? I'm using SQL Server 2008.
If you can't do the insert all over again, as #Lamak suggested, then you could perform an UPDATE this way:
UPDATE t1
SET t1.Date = s.Date
FROM Table1 AS t1
INNER JOIN
(
SELECT Item, [Date] = MAX([Date]) -- or MIN()
FROM Table2
GROUP BY Item
) AS s
ON t1.Item = s.Item;
For SQL Server you coul've use a single INSERT statement:
INSERT INTO Table1(Item, Totals, [Date])
SELECT Item, SUM(Quantity), MIN([Date]) -- It could be MAX([Date])
FROM Table2
GROUP BY Item
The easiest way is to use a simple CTAS (create table as select):
select item as item, SUM(quantity) as Q, MIN(date) as d into table2
from table1
group by item
Instead of creating a table, you could create a view, using a select statement like in #Lamak's answer. That way you wouldn't have to update the new row set each time the Table2 updates.

Resources