case in group by in a store procedure - sql-server-2005

is possible do a case in a group by?
similar to this:
select * from table
GROUP BY
CASE WHEN #Attivita=0 THEN (RANK() OVER (GROUP BY Nome,AccountID,Matricola DESC))
END
thanks

you have to group by all selected (non-aggregated) columns..
so if you select * you will need to group by all of them ...
If instead of group by you mean order by then yes you can..

No: this would make no sense.
You can't
use GROUP BY and SELECT *
use RANK in a subclause
use GROUP BY in the OVER clause
GROUP BY over a ranking function makes no sense
What are you trying to do, with input/output and schema please.
Edit, based on gaby's answer
select
*
from
(
SELECT
*, RANK() OVER (GROUP BY Nome,AccountID,Matricola DESC) as bar
from
table
) foo
ORDER BY
CASE WHEN #Attivita=0 THEN bar END

Related

BigQuery - Extract last entry of each group

I have one table where multiple records inserted for each group of product. Now, I want to extract (SELECT) only the last entries. For more, see the screenshot. The yellow highlighted records should be return with select query.
The HAVING MAX and HAVING MIN clause for the ANY_VALUE function is now in preview
HAVING MAX and HAVING MIN were just introduced for some aggregate functions - https://cloud.google.com/bigquery/docs/release-notes#February_06_2023
with them query can be very simple - consider below approach
select any_value(t having max datetime).*
from your_table t
group by t.id, t.product
if applied to sample data in your question - output is
You might consider below as well
SELECT *
FROM sample_table
QUALIFY DateTime = MAX(DateTime) OVER (PARTITION BY ID, Product);
If you're more familiar with an aggregate function than a window function, below might be an another option.
SELECT ARRAY_AGG(t ORDER BY DateTime DESC LIMIT 1)[SAFE_OFFSET(0)].*
FROM sample_table t
GROUP BY t.ID, t.Product
Query results
You can use window function to do partition based on key and selecting required based on defining order by field.
For Example:
select * from (
select *,
rank() over (partition by product, order by DateTime Desc) as rank
from `project.dataset.table`)
where rank = 1
You can use this query to select last record of each group:
Select Top(1) * from Tablename group by ID order by DateTime Desc

LIMITING MAX VALUES IN SQL

I am completely rewriting this question, I just cant crack it
IDB DB2 SQL
(from a Chicago Crime Dataset)
Which community area is most crome prone?
When I use this code, it does correctly count and sort the data
select community_area_number as community_area_number, count(community_area_number) as total_area_crime
from chicago_crime_data
group by community_area_number
order by total_area_crime desc;
the problem is, it lists all the data descending, but no matter what MAX statement I use, either in the select or the order by statement, it wont show just the max values.
The max values are 43, so I would like to to show both 'community_area_numbers' that have 43.
Instead it shows the entire list.
Here is a screenshot
also, yes I understand I can just do a LIMIT 2 command, but that would be cheating since I manually checked that there are 2 max values, but if this data changed or i didnt know that, it doesnt solve anything
thanks in advance
What you would be looking for is the standard SQL clause FETCH WITH TIES;
select community_area_number, count(*) as total_area_crime
from chicago_crime_data
group by community_area_number
order by total_area_crime desc
fetch first row with ties;
Unfortunately, though, DB2 doesn't support WITH TIES in FETCH FIRST.
The classic way (that is before we had the window functions RANK and DENSE_RANK) is to use a subquery: Get the maximum value, then get all rows with that maximum. I am using a CTE (aka WITH clause) here in order not to have to write everything twice.
with counted as
(
select community_area_number, count(*) as total_area_crime
from chicago_crime_data
group by community_area_number
)
select community_area_number, total_area_crime
from counted
where total_area_crime = (select max(total_area_crime) from counted);
(Please note that this is a mere COUNT(*), because we want to count rows per community_area_number.)
Like #topsail mentioned. You could use a rank function.
From the table you have above you could do the following
SELECT t.* FROM
(
SELECT *,
RANK() OVER (Order by Total_Area_Crime DESC) rnk
from
table1
)t
WHERE t.rnk = 1
db fiddle
So your full query should look something like this:
With cte AS (
SELECT MAX(COMMUNITY_AREA_NUMBER) AS COMMUNITY_AREA_NUMBER,
COUNT(COMMUNITY_AREA_NUMBER) AS TOTAL_AREA_CRIME
FROM CHICAGO_CRIME_DATA
GROUP BY COMMUNITY_AREA_NUMBER
ORDER BY TOTAL_AREA_CRIME DESC;
)
SELECT t.* FROM
(
SELECT *,
RANK() OVER (Order by Total_Area_Crime DESC) rnk
from
cte
)t
WHERE t.rnk = 1
It turns out the professor did want us to use the Limit command.
Here is the final answer:
SELECT COMMUNITY_AREA_NUMBER, COUNT(ID) AS CRIMES_RECORDED
FROM CHICAGO_CRIME_DATA
GROUP BY COMMUNITY_AREA_NUMBER
ORDER BY CRIMES_RECORDED DESC LIMIT 1;
thanks to all those who responded :D

sql aggregations

any ideas why this doesn't work?
select [column_name_2], max(count(distinct([column_name_1])))
from [table_name]
group by [column_name_2]
but it works if done like this
select [column_name_2], count(distinct([column_name_1])) as [x]
into #temp_table
from [table_name]
group by [column_name_2]
select max(x)
from #temp_table
Well, that's just the way SQL (the language) is defined to work. When you use GROUP BY, the corresponding SELECT list will produce a row for each group in the result. You're trying to take that result and aggregate twice, once with GROUP BY [column_name_2] and a second time with GROUP BY (), as defined by standard SQL. We can't do that in the same query expression.
The good news is you can break this up into more than one query expression:
WITH cte1 AS (
SELECT count(distinct([column_name_1])) AS cnt
FROM [table_name]
GROUP BY [column_name_2]
)
SELECT MAX(cnt) FROM cte1
;
or use a derived table.
You can even order the initial query result by cnt DESC and limit the result to the first row.
In your case, you may not want just the MAX, but also the other column.
With SQL Server, which you may be using. Note: You should add a database specific tag to the question.
SELECT TOP 1 [column_name_2], count(distinct([column_name_1])) AS cnt
FROM [table_name]
GROUP BY [column_name_2]
ORDER BY cnt DESC
;
I don't understand "this doesn't work", what were you expecting and what did you get? Normally you include the GROUP BY value in the result set. So it would be:
select [column_name_2], max(cnt) cnt
from (select [column_name_2], count(distinct [column_name_1]) cnt
from [table_name]
group by [column_name_2]) x
group by [column_name_2]
Ok, after reading your comment I think above is what you are looking for.
SELECT [column_name_two]
, max(x) x
FROM (
SELECT [column_name_two]
, COUNT(DISTINCT [column_name_one]
FROM table_name
GROUP BY [column_name_two]
) AS Tbl
GROUP BY [column_name_two]

Printing same rows twice in SQL Server

I'm using this query
SELECT
[SCORECARD_NAME], [SCORE_NAME],
[TOTAL_ROWS], [VALID_PERCENTAGE], [INVALID_ROWS]
FROM
{table_name}
and I'm getting the result twice. I'm not getting why its happening like that
what is the solution for this?
You can use SELECT DISTINCT, or here is an option using a CTE with a window function:
;WITH CTE AS (
SELECT [SCORECARD_NAME], [SCORE_NAME], [TOTAL_ROWS], [VALID_PERCENTAGE],[INVALID_ROWS],
ROW_NUMBER() OVER (PARTITION BY [SCORECARD_NAME]
ORDER BY [SCORECARD_NAME]) AS DuplicateCount
FROM Table_Name
)
SELECT * FROM CTE WHERE DuplicateCount = 1;
In case you want rows with same entries to be displayed once then use distinct:
SELECT DISTINCT
[SCORECARD_NAME], [SCORE_NAME], [TOTAL_ROWS],
[VALID_PERCENTAGE], [INVALID_ROWS]
FROM
{table_name};
Let me know in case of any queries.

How to avoid duplicating statements with grouping functions?

I have a t-sql query where sum function is duplicated.
How to avoid duplicating those statements?
select
Id,
sum(Value)
from
SomeTable
group by
Id
having
sum(Value) > 1000
It look like table aliasing is not supported.
I think with should work:
with tmptable (id,sumv)
as
(select
Id,
sum(Value) as sumv
from
SomeTable
group by
Id
)
select
id,
sumv
from
tmptable
where
sumv>1000
And a fiddle:
http://sqlfiddle.com/#!6/0d3f2/2
You need to remove the sum(Value) from the group by clause.
You can use GROUP BY 1, 2 to group by (in this case) the first and second columns, and thus avoid duplication in the GROUP BY clause.