Querying the lowest values in a table - sql-server

I would like to executing this query in a table below, but I can't, it is saying that needs to use having and group by, someone can show me how to it, I am using SQL Server.
SELECT
products.name AS item,
users.name AS buyer,
auctionValues.value AS value
FROM
auctionValues
JOIN
products ON (auctionValues.productId = products.id)
JOIN
auctionOrders ON (auctionsValues.auctionOrderId = auctionOrders.id)
AND (auctionOrders.id = '987')
JOIN
users ON auctionValues.userId = users.id
WHERE
auctionValues.value >= MIN(auctionValues.value) * 1.05
ORDER BY
products.id ASC,
auctionValues.value DESC

This may works :
;with minValues as (
select productId, MIN(auctionValues.value) * 1.05 as minValue
)
SELECT
products.name AS item,
users.name AS buyer,
auctionValues.value AS value
FROM
auctionValues
JOIN
products ON (auctionValues.productId = products.id)
JOIN
auctionOrders ON (auctionsValues.auctionOrderId = auctionOrders.id)
AND (auctionOrders.id = '987')
JOIN
users ON auctionValues.userId = users.id
WHERE
auctionValues.value >= (SELECT minValue from minValues WHERE products.Id = minValues.productId)
ORDER BY
products.id ASC,
auctionValues.value DESC

Typically you group by the columns which are not in the min function.
Seen the following links.
https://learn.microsoft.com/en-us/sql/t-sql/queries/select-group-by-transact-sql?view=sql-server-2017
https://learn.microsoft.com/en-us/sql/t-sql/functions/aggregate-functions-transact-sql?view=sql-server-2017

You can't mix aggregate functions like MIN to non-aggregated columns without including them in GROUP BY. However in your case you just need to use a SELECT subquery to get the MIN value you are using in the condition.
Change this part:
WHERE auctionValues.value >= (SELECT MIN(auctionValues.value) FROM auctionValues) * 1.05

Related

SQL Query Group by Count and Left Join Tables

i need your help! I got some simple SQL skills, but this query kills me...
My Tables
Now i want the TOP5 WorkTimes on the Equipment (What Equipment got the longest WorkTime).
I want this OUTPUT:
MY Query:
SELECT
Equipment, EquipmentName, count(Equipment) as Count
FROM
Operations o
LEFT JOIN Orders ord ON ord.Id = o.[Order]
LEFT OUTER JOIN Equipments e ON ord.Equipment = e.EquipmentNumber
GROUP BY
Equipment, EquipmentName
ORDER BY Count DESC;
Another Question is how i can show o.Worktime?
i got an error with GroupBy...
please help me Thanks!
You can try this query:
select equip_nr,
(select equipmentname from table_equipments where equipmentnr = [to].equip_nr) equip_name,
sum(timeInMins) / 60.0 Worktime
from (
select (select equipmentnr from table_orders where id = [to].[order]) equip_nr,
case when workunittime = 'RH' then worktime * 60 else worktime end timeInMins
from table_operations [to]
where exists(select 1 from table_orders
where [to].[order] = id
and location = '152')
and [start] >= '2018-07-01 00:00:00.000' and [start] < '2018-08-01 00:00:00.000'
) [to] group by equip_nr
By the way, LEFT JOIN is equivalent to LEFT OUTER JOIN.
Just use SUM(worktime) as aggregate function, instead of COUNT(Equipment)
SELECT
e.[ID_Equipment]
, Name
, SUM( IIF(o.WorkUnitTime='MIN', worktime/60.0, worktime) ) as WorktimeMIN
FROM
Operations o
LEFT JOIN Orders ord ON ord.ID_Order = o.ID_Order
LEFT OUTER JOIN Equipment e ON ord.ID_Equipment = e.ID_Equipment
GROUP BY
e.[ID_Equipment]
, Name
ORDER BY
WorktimeMIN DESC
See SQL Fiddle here: http://sqlfiddle.com/#!18/5b5ed/11

Aggregate query grouping

The query below seems to work despite being wrong.
The Color column doesn't belong in an aggregate function but I don't want to group by Color. I want to return the color for the minimum priority grouped by Vehicle.
I hope the below is enough to work with - I was hoping for a quick answer but will go into more detail if necessary.
SELECT alert.VehicleID,
min(hotcol.[Priority]) as [Priority]
min(hotcol.Color) as Color,
FROM [ALERTS] alert
INNER JOIN [HOTLISTS] hotlist ON alert.[HotlistID] = hotlist.[HotlistID]
INNER JOIN [HOTLIST_COLORS] hotcol ON hotlist.ColorID = hotcol.ColorID
WHERE VehicleID = 17513851
GROUP BY alert.VehicleID
You can use the ranking function ROW_NUMBER to do this. Something like this:
WITH CTE
AS
(
SELECT
alert.VehicleID,
hotcol.Color,
hotcol.[Priority],
ROW_NUMBER() OVER(PARTITION BY alert.VehicleID
ORDER BY hotcol.[Priority]) AS RN
FROM [ALERTS] alert
INNER JOIN [HOTLISTS] hotlist ON alert.[HotlistID] = hotlist.[HotlistID]
INNER JOIN [HOTLIST_COLORS] hotcol ON hotlist.ColorID = hotcol.ColorID
WHERE VehicleID = 17513851
)
SELECT
VehicleID,
Color,
[Priority]
FROM CTE
WHERE rn = 1;
The ROW_NUMBER function will give a ranking number for each alert.VehicleID and each group will be ordered by priority. Then WHERE rn = 1 will filter out all the rows except the minimum one which has rn = 1.

How to get rows with Maximum id with condition of a table in SQL Server

i have a table similar this
id-value-RowInid
1-xy-1
1-xx-2
1-xz-3
2-xx-1
2-xr-2
3-xq-1
4-xa-1
4-xc-2
...
i need a function for this table with similar output to get maximum of RowInid in separated id group
1-xz-3
2-xr-2
3-xq-1
4-xc-2
...
You just need to use MAX(RowInid) with GROUP BY Id, value
SELECT ID, VALUE, MAX(RowInid) FROM myTable GROUP BY ID, VALUE
EDIT:
As you updated your question, you can get value field using sub-query like this:
SELECT ID, VALUE, RowInid
FROM myTable t1 WHERE RowInid =
(
SELECT MAX(RowInid) FROM myTable WHERE id = t1.id GROUP BY id
)
ORDER BY id ASC;
You can also achieve this using INNER JOIN like this:
SELECT t2.ID, VALUE, t2.RowInid FROM myTable t1
INNER JOIN
(
SELECT ID, MAX(RowInid) AS RowIniD FROM myTable GROUP BY ID
) AS t2
ON t1.ID = t2.ID AND t1.RowInid = t2.RowInid
ORDER BY t1.ID ASC;
See this SQLFiddle
See more about GROUP BY and MAX in SQL Server.
no need for group by or max at all
select id, value, rowinid from
( select *, row_number() over (partition by id, order by rowinid desc) rn from yourtable ) v
where rn = 1
Try with,
Use Sub Query to get Id, Value and Max RowInid,
SELECT m1.[Id],m1.Value, m1.RowInid
FROM [Practice].[dbo].[myTable] m1 WHERE RowInid = (SELECT MAX(m2.RowInid) FROM [Practice].[dbo].[myTable] m2 WHERE M1.Id = m2.Id GROUP BY Id)
above query return result like:
4-xx-2
3-xx-1
2-xx-2
1-xx-3
To Ascending this use,
SELECT m1.[id],m1.Value, m1.RowInid
FROM [Practice].[dbo].[myTable] m1 WHERE m1.RowInid = (SELECT MAX(m2.RowInid) FROM [Practice].[dbo].[myTable] m2 WHERE M2.id = m1.id GROUP BY id) ORDER BY m1.id ASC

select top 1 with a group by

I have two columns:
namecode name
050125 chris
050125 tof
050125 tof
050130 chris
050131 tof
I want to group by namecode, and return only the name with the most number of occurrences. In this instance, the result would be
050125 tof
050130 chris
050131 tof
This is with SQL Server 2000
I usually use ROW_NUMBER() to achieve this. Not sure how it performs against various data sets, but we haven't had any performance issues as a result of using ROW_NUMBER.
The PARTITION BY clause specifies which value to "group" the row numbers by, and the ORDER BY clause specifies how the records within each "group" should be sorted. So partition the data set by NameCode, and get all records with a Row Number of 1 (that is, the first record in each partition, ordered by the ORDER BY clause).
SELECT
i.NameCode,
i.Name
FROM
(
SELECT
RowNumber = ROW_NUMBER() OVER (PARTITION BY t.NameCode ORDER BY t.Name),
t.NameCode,
t.Name
FROM
MyTable t
) i
WHERE
i.RowNumber = 1;
select distinct namecode
, (
select top 1 name from
(
select namecode, name, count(*)
from myTable i
where i.namecode = o.namecode
group by namecode, name
order by count(*) desc
) x
) as name
from myTable o
SELECT max_table.namecode, count_table2.name
FROM
(SELECT namecode, MAX(count_name) AS max_count
FROM
(SELECT namecode, name, COUNT(name) AS count_name
FROM mytable
GROUP BY namecode, name) AS count_table1
GROUP BY namecode) AS max_table
INNER JOIN
(SELECT namecode, COUNT(name) AS count_name, name
FROM mytable
GROUP BY namecode, name) count_table2
ON max_table.namecode = count_table2.namecode AND
count_table2.count_name = max_table.max_count
I did not try but this should work,
select top 1 t2.* from (
select namecode, count(*) count from temp
group by namecode) t1 join temp t2 on t1.namecode = t2.namecode
order by t1.count desc
Here are to examples that you could use but the temp table use is more efficient than the view, but was done on a small data sample. You would want to check your own statistics.
--Creating A View
GO
CREATE VIEW StateStoreSales AS
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank'
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
GO
SELECT * FROM StateStoreSales
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP VIEW StateStoreSales
---Using a Temp Table
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank' INTO #TEMP
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
SELECT * FROM #TEMP
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP TABLE #TEMP

SQL Server 2005 Syntax Help - "Select Info based upon Max Value of Sub Query"

The objective is below the list of tables.
Tables:
Table: Job
JobID
CustomerID
Value
Year
Table: Customer
CustomerID
CustName
Table: Invoice
SaleAmount
CustomerID
The Objective
Part 1: (easy) I need to select all invoice records and sort by Customer (To place nice w/ Crystal Reports)
Select * from Invoice as A inner join Customer as B on A.CustomerID = B.CustomerID
Part 2: (hard) Now, we need to add two fields:
JobID associated with that customer's job that has the Maximum Value (from 2008)
Value associated with that job
Pseudo Code
Select * from
Invoice as A
inner join Customer as B on A.CustomerID = B.CustomerID
inner join
(select JobID, Value from Jobs where Job:JobID has the highest value out of all of THIS customer's jobs from 2008)
General Thoughts
This is fairly easy to do If I am only dealing with one specific customer:
select max(JobId), max(Value) as MaxJobID from Jobs where Value = (select max(Value) from Jobs where CustomerID = #SpecificCustID and Year = '2008') and CustomerID = SpecificCustID and CustomerID = '2008'
This subquery determines the max Value for this customer in 2008, and then its a matter of choosing a single job (can't have dupes) out of potential multiple jobs from 2008 for that customer that have the same value.
The Difficulty
What happens when we don't have a specific customer ID to compare against? If my goal is to select ALL invoice records and sort by customer, then this subquery needs access to which customer it is currently dealing with. I suppose this can "sort of" be done through the ON clause of the JOIN, but that doesn't really seem to work because the sub-sub query has no access to that.
I'm clearly over my head. Any thoughts?
How about using a CTE. Obviously, I can't test, but here is the idea. You need to replace col1, col2, ..., coln with the stuff you want to select.
Inv( col1, col2, ... coln)
AS
(
SELECT col1, col2, ... coln,
ROW_NUMBER() OVER (PARTITION BY A.CustomerID
ORDER BY A.Value DESC) AS [RowNumber]
FROM Invoice A INNER JOIN Customer B ON A.CustomerID = B.CustomerID
WHERE A.CustomerID = #CustomerID
AND A.Year = #Year
)
SELECT * FROM Inv WHERE RowNumber = 1
If you don't have a CustomerID, this will return the top value for each customer (that will hurt on performance tho).
The row_number() function can give you what you need:
Select A.*, B.*, C.JobID, C.Value
from
Invoice as A
inner join Customer as B on A.CustomerID = B.CustomerID
inner join (
select JobID, Value, CustomerID,
ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY Value DESC) AS Ordinal
from Jobs
WHERE Year = 2008
) AS C ON (A.CustomerID = C.customerID AND C.Ordinal = 1)
The ROW_NUMBER() function in this query will order by value in descending order and the PARTITION BY clause will do this separately for each different value of CustomerID. This means that the highest Value for each customer will always be 1, so we can join to that value.
The over function is an awesome, but often neglected function. You can use it in a subquery to pull back your valid jobs, like so:
select
a.*
from
invoice a
inner join customer b on
a.customerid = b.customerid
inner join (select customerid, max(jobid) as jobid, maxVal from
(select customerid,
jobid,
value,
max(value) over (partition by customerid) as maxVal
from jobs
where Year = '2008') s
where s.value = s.maxVal
group by customerid, maxVal) c on
b.customerid = c.customerid
and a.jobid = c.jobid
Essentially, that first inner query looks like this:
select
customerid,
jobid,
value,
max(value) over (partition by customerid) as maxVal
from jobs
where Year = '2008'
You'll see that this pulls back all of the jobs, but with that additional column which lets you know what the maximum value is for each customer. With the next subquery, we filter out any rows that have value and maxVal equal. Additionally, it finds the max JobID based on customerid and maxVal, because we need to pull back one and only one JobID (as per the requirements).
Now, you have a complete listing of CustomerID and JobID that meet the conditions of having the highest JobID that contains the maximum Value for that CustomerID in a given year. All that's left is to join it to Invoice and Customer, and you're good to go.
Just to be complete with the non row_number solution for those < MSSQL 2005. Personanly, I find it easier to follow myslef...but that could be biased considering how much time I spend in MSSQL 2000 vs 2005+.
SELECT *
FROM Invoice as A
INNER JOIN Customer as B ON
A.CustomerID = B.CustomerID
INNER JOIN (
SELECT
CustomerId,
--MAX in case dupe Values.
==If UC on CustomerId, Value (or CustomerId, Year, Value) then not needed
MAX(JobId) as JobId
FROM Jobs
JOIN (
SELECT
CustomerId,
MAX(Value) as MaxValue
FROM Jobs
WHERE Year = 2008
GROUP BY
CustomerId
) as MaxValue ON
Jobs.CustomerId = MaxValue.CustomerId
AND Jobs.Value = MaxValue.MaxValue
WHERE Year = 2008
GROUP BY
CustomerId
) as C ON
B.CustomerID = C.CustomerID

Resources