Count no of rows with group by clause in criteria - sql

is there a way to write hibernate criteria for the following sql:
select count(*) from tableA group by columnA, columnB, columnC;
Basically, I want to exclude the group property from the select clause which is added by default.
Example:
session.createCriteria(TableA.class)
.setProjection(Projections.projectionList()
.add(Projections.groupProperty("columnA"))
.add(Projections.groupProperty("columnB"))
.add(Projections.groupProperty("columnC"))
.add(Projections.rowCount()));
will result in
select columnA, columnB, columnC, count(*) from tableA group by columnA, columnB, columnC;
Thanks.

refer below code::
Integer totalResult = ((Number)criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
You can also try this:::
int count = ((Long)getSession().createQuery("select count(*) from table_a group by column_a").uniqueResult()).intValue();

Related

SQL: Add a SUM(ColumnA) AS ColumnB to a query returning ColumnA

I have a query that returns a number of columns, including ColumnA (which is numerical).
I want to add an additional column to the end of the query that returns the sum of ColumnA
ColumnA
ColumnB
10
37
20
37
5
37
2
37
SELECT
ColumnA,
SUM(ColumnA) AS ColumnB
FROM
Table
The code above doesn't work, but I'm not sure how to create something that will.
I think you need this query:
SELECT ColumnA, (SELECT SUM(ColumnA) FROM table) as ColumnB
FROM table
Something like
SELECT
ColumnA,
ColumnASum
FROM Table
LEFT JOIN (SELECT SUM(columnA) ColumnASum FROM Table)
ON TRUE;
Should work
You could create a variable of the SUM() first.
DECLARE #ColumnB int
SET #ColumnB = (SELECT SUM(ColumnA) FROM Table)
SELECT ColumnA, #ColumnB
FROM Table
This should give you what you need.
I would use CROSS APPLY.
SELECT Table.ColumnA
,CA.ColumnB
FROM Table
CROSS APPLY (SELECT SUM(ColumnA) ColumnB FROM Table) CA
You basically define a subquery that outputs an aggregate value that you can have as another column.

How to handle order of fields in groupby line based on user's selection?

I have a query like that in Sql Server 2008:
Select ColumnA, ColumnB, ColumnC, ColumnD, sum(value1), sum(value2), sum(value3)...
from Table
group by ColumnA, ColumnB, ColumnC, ColumnD
What I need to do is to change the column order in the GroupBy line based on user's demand. For example, User1 wants to see the results: group by ColumnB, ColumnA, ColumnD, ColumnC, where User2 wants to see the results: group by ColumnD, ColumnA, ColumnC, ColumnB. Basically, the order in the groupby segment should be dynamic based on user's selection. There are 24 potential order...
What is the best way to handle it?
I came up with an idea like:
declare #groupbyOrder int = 20 --let's say 20
Select ColumnA, ColumnB, ColumnC, ColumnD, sum(value1), sum(value2), sum(value3)...
from Table
group by (case when #groupbyOrder = 1 then ColumnA, ColumnB, ColumnC, ColumnD)
...
when #groupbyOrder = 20 then ColumnD, ColumnB, ColumnC, ColumnA)
...)
But it did not work and I don't think it is a good way to manage the issue. Any advice will be appreciated.
Just another Dynamic SQL option where you the selected columns may include expressions and thus your group/order by will exclude the alias.
Example
Declare #Cols varchar(max)
Declare #GroupOrder varchar(max)
Declare #SQL varchar(max)
Select #Cols = Cols
,#GroupOrder = isnull(GroupOrder,Cols)
From (values (1,'ColA,ColB',null) -- Notice GrpBy is null
,(2,'ColA,ColB=cast(ColB as date)','ColA,cast(ColB as date)') -- can include expressions
-- Add more otions here
) A(ID,Cols,GroupOrder)
Where ID=2
Set #SQL = '
Select '+#Cols +',sum(value1),sum(value)
From Table
Group By '+#GroupOrder +'
Order By '+#GroupOrder
Print #SQL
--Exec(#SQL)
Generated SQL
Select ColA,ColB=cast(ColB as date),sum(value1),sum(value)
From Table
Group By ColA,cast(ColB as date)
Order By ColA,cast(ColB as date)
Huh? The group by doesn't need to change, only the select. The order by expressions in a group by has no effect on what the result set looks like.
This is very strange request, but I think four variables make more sense than 1:
Select (case when #firstColumn = 'A' then ColumnA
when #firstColumn = 'B' then ColumnB
. . .
end) as firstcolumn,
(case when #secondColumn = 'A' then ColumnA
when #secondCOlumn = 'B' then ColumnB
. . .
end) as secondcolumn,
. . .
sum(value1), sum(value2), sum(value3)...
from Table t
group by ColumnA, ColumnB, ColumnC, ColumnD;
My guess is that you really care about order by -- group by rows are in an arbitrary order. If so, you should ask another question with sample data and an explanation of what you need.
Expanding on Grodon's comment, you can use dynamic sql to build the sql statement using the user's selected preference.
Get the user's preferred order as a string, such as
'group by Column1,Column2'
Then append that to your static query text,
'Select ColumnA, ColumnB, ColumnC, ColumnD, sum(value1), sum(value2), sum(value3) from Table'
and execute the final statement:
'Select ColumnA, ColumnB, ColumnC, ColumnD, sum(value1), sum(value2), sum(value3) from Table' + 'group by Column1,Column2'

Inserting values based on unique values of another table(Normalization)

I have Table1 with columns A,B & C.
I want to create Table 2 and create Primary Key for values in ColumnA, Table1(unique), and then accordingly populate values B and C from Table1 (based on unique values of Column A).
Any help will be appreciated.
EDIT:I am using SQL server and tried using INSERT INTO...SELECT DISTINCT.
If you are using MS SQL Server, Try this
WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(PARTITION BY ColumnA ORDER BY ColumnA),
ColumnA,
ColumnB,
ColumnC
FROM YourTable
)
INSERT INTO Table2
(
ColumnA,
ColumnB,
ColumnC
)
SELECT
ColumnA,
ColumnB,
ColumnC
FROM CTE
WHERE RN = 1

Group BY on Condition basis

I have data in following way....
ColumnA ColumnB
7675 22838
7675 24907
7675 NULL
I want the results in following way.....
ColumnA ColumnB
7675 2 (need total count for Not Null value)
7675 0 (need count 0 for NULL value)
SELECT ColumnA, COUNT(ColumnB) ColumnB
FROM YourTable
GROUP BY ColumnA
UNION ALL
SELECT ColumnA, 0
FROM YourTable
WHERE ColumnB IS NULL
GROUP BY ColumnA
You could introduce a calculated column indicating whether ColumnB is null or not and use it as a grouping criterion together with ColumnA:
SELECT
t.ColumnA,
ColumnB = COUNT(t.ColumnB)
FROM
dbo.YourTable AS t
CROSS APPLY
(SELECT CASE WHEN t.ColumnB IS NULL THEN 1 ELSE 0 END) AS x (SubGroup)
GROUP BY
t.ColumnA,
x.SubGroup
ORDER BY
t.ColumnA,
x.SubGroup
;
The COUNT(t.ColumnB) expression would always be NULL for a null subgroup, and for the corresponding non-null subgroup it would return the number of the non-null entries.
select columnA,
count(columnB) as non_null_count,
sum(columnB is null) as null_count
from your_table
group by ColumnA
you could easily do with a count and sum which may be faster if there are a lot of rows rather than selecting all of the rows twice with a UNION
SELECT columna, columnb, SUM(mycount)
FROM
( SELECT *, COUNT(columnb) as mycount
FROM test
GROUP BY columnb
)t
GROUP BY mycount
ORDER BY CASE WHEN mycount = 0 THEN 1 ELSE 2 END DESC;
Fiddle Demo

SQL Server 2005 - Select top N plus "Other"

I have a table for which I want to select top the 5 rows by some column A. I also want to have a 6th row titled 'Other' which sums the values in column A for all but the top 5 rows.
Is there an easy way to do this? I'm starting with:
select top 5
columnB, columnA
from
someTable t
order by
columnA desc
Not tested, but try something like this:
select * from (
select top 5
columnB, columnA
from
someTable t
order by
columnA desc
union all
select
null, sum(columnA)
from
someTable t
where primaryKey not in (
select top 5
primaryKey
from
someTable t
order by
columnA desc
)
) a
select top 5 columnB, columnA
from someTable
order by columnA desc
select SUM(columnA) as Total
from someTable
Do the subtraction on the client side.
100% untested, and off the top of my head, but you can give something like this a go. If I have a chance to test tonight I'll update the post, but there's a bottle of wine open for dinner and it's Friday night... :)
WITH CTE AS
(
SELECT
ColumnB,
ColumnA,
ROW_NUMBER() OVER (ORDER BY ColumnB) AS RowNumber
FROM
dbo.SomeTable
)
SELECT
CASE WHEN RowNumber <= 5 THEN ColumnB ELSE 'Other' END AS ColumnB,
SUM(ColumnA) AS ColumnA
FROM
CTE
GROUP BY
CASE WHEN RowNumber <= 5 THEN ColumnB ELSE 'Other' END
ORDER BY
MIN(RowNumber)
EDIT: Looks like this worked after a couple of silly syntax errors. I've corrected those, so it should work as listed above now. I can't speak to performance on a large data set though, but it's worth giving it a shot.
This is off the top of my head, and i will garuntee horribly efficient:
SELECT TOP 5 columnB, columnA
FROM comTable t
ORDER BY columnA desc
UNION
SELECT 'Other', (A.Sum - B.Sum) AS Summary
FROM (SELECT SUM(columnA) FROM someTable) A
JOIN (SELECT SUM(One) FROM
(SELECT TOP 5 columnA FROM someTable ORDER BY columnA DESC)) B
I have recently used the EXCEPT statemnet a lot: (Not tested but I give it a go)
select top 5
columnB, columnA
from
someTable t
order by
columnA desc
UNION ALL
SELECT 'OTHER' ColumnB, SUM(ColumnA)
FROM
(SELECT ColumnB, ColumnA
FROM someTable t
EXCEPT
select top 5
columnB, columnA
from
someTable t
order by
columnA desc
) others