T-SQL order by and take only the highest value - tsql

I have a table where i want to retrieve the highest values of a category
ea:
UserA catA 4
userA catA 200
userA catB 100
UserA catA 50
userB catA 150
userB catC 10
userB catC 300
it should return
userA catA 200
userA catB 100
userB catA 150
userB catC 300
Order by and then take only the highest value.
And i wonder what's the best way to do this.

Select column1, column2, max(column3) as MaxColumn3 from TableName group by column1, column2
as simple as that.

Another option can be using MAX() function with Partition By clause as follows
Select
distinct [user], category, max([value]) over (partition by [user], [category]) as MaxValue
from UserCategoryValues
Many aggregation functions can be used with Partition By clause in SQL

Select [User], Category,max(Value) from UserCategory group by [User], Category order by [User]

Related

Choose the duplicates and pick based on non duplicate column

I need to write a query on below table to fetch the records only when the same email and name is shared by more than 1 member. In below example, I need resultset as
100 a#a.com nameA
300 a#a.com nameA
Table
Member email name
100 a#a.com nameA
100 a#a.com nameA
300 a#a.com nameA
200 b#b.com nameB
I doubt you have typo and you mean 100 instead of 200 in your expected result. If so, then there is one way:
with your_table(Member, email , name ) as (
select 100,'a#a.com','nameA' union all
select 100,'a#a.com','nameA' union all
select 300,'a#a.com','nameA' union all
select 200,'b#b.com','nameB'
)
-- below is actual query:
select distinct your_table.*
from your_table
inner join (
select email , name from your_table
group by email , name
having count(distinct Member) > 1
) t
on your_table.email = t.email and your_table.name = t.name

counting in sql in subquery in the table

DNO DNAME
----- -----------
1 Research
2 Finance
EN ENAME CITY SALARY DNO JOIN_DATE
-- ---------- ---------- ---------- ---------- ---------
E1 Ashim Kolkata 10000 1 01-JUN-02
E2 Kamal Mumbai 18000 2 02-JAN-02
E3 Tamal Chennai 7000 1 07-FEB-04
E4 Asha Kolkata 8000 2 01-MAR-07
E5 Timir Delhi 7000 1 11-JUN-05
//find all departments that have more than 3 employees.
My try
select deptt.dname
from deptt,empl
where deptt.dno=empl.dno and (select count(empl.dno) from empl group by empl.dno)>3;
here is the solution
select deptt.dname
from deptt,empl
where deptt.dno=empl.dno
group by deptt.dname having count(1)>3;
select
*
from departments d
inner join (
select dno from employees group by dno having count(*) > 3
) e on d.dno = e.dno
There are many approaches to this problem but almost all will use GROUP BY and the HAVING clause. That clause allows you to filter results of aggregate functions. Here it is used to choose only those records where the count is greater than 3.
In the query structure used above the group by is handled on the employee table only, then the result (which is known as a derived table) is joined by an INNER JOIN to the departments table. This inner join only allows matching records so this has the effect of filtering the departments table to only those which have a count() of greater than 3.
An advantage of this query structure is fewer records are joined, and also that all columns of the departments table are available for reporting. Disadvantage of this structure is the the count() of employees per department isn't visible.

nested select using count to tally each row in Postgres

I have a table where each row is a unique order with a unique order_id, but users can have multiple rows/orders.
Orders table -> order_id, user_id, orderedat (datetime), sales
I am trying to return a query that calculates, for each order_id, how many previous orders the associated user has made. (Essentially, does this row represent the user's first order? 5th order? 20th order? etc.)
I'm trying something like this nested select, but am getting an error "more than one row returned by a subquery used as an expression."
SELECT
order_id,
user_id,
COUNT (order_id) AS order_n
FROM
orders
WHERE orderedat >= (
SELECT
orderedat
FROM
fulfillments
GROUP BY
order_id
)
GROUP BY
order_id
Any thoughts on how to achieve this in postgres?
///////////////
Further complication: with another column called "Status," how to only count rows with specific values in Status? I'd like to just skip orders in the number unless they have a status of "paid" or "placed". For example:
data:
order_id user_id orderedat status
001 max 10/1/14 paid
002 max 10/20/14 placed
003 max 10/21/14 cancelled
004 bill 10/5/14 deleted
005 max 10/31/14 paid
006 bill 10/24/14 placed
results:
order_id user_id orderedat orders_so_far
001 max 10/1/14 1
002 max 10/20/14 2
003 max 10/21/14 null
005 max 10/31/14 3
004 bill 10/5/14 null
006 bill 10/24/14 1
This can be done using a window function:
SELECT order_id,
user_id,
orderdat,
row_number() over (partition by user_id order by orderedat ) as orders_so_far
FROM orders
order by user_id, orderdat

Get total count per ID change

how can I get a total count of sheets per change of sheet
example:
select sheetID,
..
from SomeTable
results look something like this:
sheetID
-----------
1000
1000
1000
1000
3000
3000
3000
so I want something like this:
select sheetID,
count(sheetID) as TotalsheetCount
from SomeTable
I just don't know how to break the count up per change of sheetID.
So I'd end up with this essentially:
sheetID TotalsheetCount
-------- -----------
1000 4
1000 4
1000 4
1000 4
3000 3
3000 3
3000 3
so 4 is because there are 4 1000s, 3 because there are 3 3000s. I am wanting to repeat the total count for that sheetID for each row, even though it's repeating, I want to provide that.
UPDATE, here's what I did per the replies but I'm getting way too many results now as compoared to the count where I did not add that partition count before
select MainTable.sheetID,
COUNT(SomeTable.sheetID)OVER(PARTITION BY SomeTable.sheetID) AS TotalSheetCount
table2.SomeField1,
table2.SomeField1
from MainTable
join (select distinct Sales.SalesKey from SomeLongTableName_Sales) sales on sales.SheetKey = MainTable.sheetKey
left outer join Site on MainTable.SiteKey = Site.SiteKey
join Calendar on sales.Date >= Calendar.StartDate
and sales.Date < Calendar.EndDate
group by SomeTable.sheetID
the joins and stuff is more realistic to my real query but formatted for this post to hide real field and table names.
You probably want to use a GROUP BY:
SELECT sheetID, COUNT(sheetID) AS TotalsheetCount
FROM dbo.SomeTable
GROUP BY sheetID
I am wanting to repeat the total count for that sheetID for each row,
even though it's repeating, I want to provide that
If you're using at least SQL-Server 2005, you can use a CTE with COUNT + OVER-clause, otherwise use a sub-query:
WITH CTE AS
(
SELECT sheetID,
COUNT(sheetID)OVER(PARTITION BY sheetID) AS TotalsheetCount
FROM SomeTable
)
SELECT sheetID, TotalsheetCount FROM CTE
Use the GROUP BY clause in a subquery to select the counts:
SELECT sheetID,
count(sheetID) as TotalsheetCount
FROM SomeTable
GROUP BY sheetID
This would make your whole query look like this:
SELECT t.sheetID,
counts.TotalsheetCount
FROM SomeTable t,
(SELECT sheetID, count(sheetID) as TotalsheetCount FROM SomeTable GROUP BY sheetID) counts
WHERE t.sheetID = counts.sheetID
It looks like you need a group-by expression:
select sheetID,
count(*) as TotalsheetCount
from SomeTable
group by sheetID
Is that it?
DC

SPROC T-SQL Syntax to return results if rows exist on multiple days

what I need to test for on my table is if there are rows for a given user id and order id on two separate days (DATETIME field for a timestamp).
I'm pretty sure I'd need a having clause and that's why I'm here...that frightens me terribly.
Having shouldn't scare you, it is just a "Where" on an aggregated field:
Select UserID, Count(*) From OrderTbl Group By UserID Having Count(*) > 1
That'll give you all the Users that have multiple orders.
Select UserID, Count(*) From OrderTbl Where (UserID=#UserID) Group By UserID Having Count(*) > 1
will give you the count if there are multiple records for the user id in #UserID and null if not.
if exists (Select UserID, Count(*) From OrderTbl Where (UserID=#UserID) Group By UserID
Having Count(*) > 1) Select 1 else Select 0
will return a 1 if there are multiple records for the User, 0 if not.
Update: Didn't realize that you could have multiple orders per day. This query will do what you want:
With DistinctDates as (Select Distinct UserID, [DATE] From OrderTbl Where (UserID=#UserID))
Select UserID, Count(*) From DistinctDates
Group By UserID Having Count(*) > 1
I am not sure if I understood your question, but this may work for you. The HAVING is your friend and you can still use the WHERE clause. This should let you know what order and user id combo is occuring more than once in the table.
SELECT [UserId], [OrderId]
FROM OrderTable
WHERE UserId = #UserId
AND OrderId = #OrderId
GROUP BY UserId, OrderId
HAVING Count(*) > 1