SQL Server - Select multiple Columns Group By 1 Column - sql

I have looked at many examples of selecting many columns but only grouping by 1 column and mine seem to give me duplicate results. See below I would like to select all the columns in my table but would like to only GROUP BY VehicleId. On the screenshot you'll see that the results are actually not grouped by VehicleId.
Any idea on what I am doing wrong?
Try 1:
SELECT
h.*,
TotalFines = 1,
TotalIncidents = 1,
TotalVehicleAllocations = 1,
TotalVehicleConditions = 1,
TotalMileageApplications = 1
FROM
(
SELECT h1.VehicleId FROM [dbo].[VehicleHistory] h1 GROUP BY h1.VehicleId
) GroupedList
INNER JOIN [dbo].[VehicleHistory] h ON GroupedList.VehicleId=h.VehicleId
ORDER BY
h.VehicleId;
Try 2:
SELECT t1.* FROM VehicleHistory t1
INNER JOIN
(
SELECT VehicleId FROM VehicleHistory GROUP BY VehicleId
) t2
ON t1.VehicleId=t2.VehicleId
Both queries produce the same results with duplicate rows for each VehicleId as per below:
Here's my expected results below. The results are a query produced by Entity Framework. But I would like to rewrite the linq query into T-SQL:

This is because you are gtouping in subquery (which would be same as SELECT DISTINCT h1.VehicleId FROM [dbo].[VehicleHistory] h1):
SELECT h1.VehicleId FROM [dbo].[VehicleHistory] h1 GROUP BY h1.VehicleId
and then you are joining in on that column, which can cause duplicates to occur (you have duplicate IDs in VehicleHistory).
All you need to do is:
SELECT VehicleId,
MAX(DateUpdated) DateUpdated, --or other aggregate function
--rest of your columns in appropriate aggreagte functions
FROM VehicleHistory
GROUP BY VehicleId

Related

How to take count of distinct rows which have a specific column with NULL values is all rows

I have a table CodeResult as follows:
Here we can notice that Code 123 alone has a Code2, that has a value in Result. I want to take a count of distinct Codes that has no values at all in Result. Which means, in this example, I should get 2.
I do not want to use group by clause because it will slow down the query.
Below code gives wrong result:
Select count(distinct code) from CodeResult where Result is Null
One method is two levels of aggregation:
select count(*)
from (select code
from t
group by code
having max(result) is null
) c;
A more clever method doesn't use a subquery. It counts the number of distinct codes and then removes the ones that have a result:
select ( count(distinct code) -
count(distinct case when result is not null then code end )
)
from t;
You simply can't avoid a GROUP BY: In all DBMSs I know, the query plan you get from a:
SELECT DISTINCT a,b,c FROM tab; ,
is the same as the one for:
SELECT a,b,c FROM tab GROUP BY a,b,c;
The following query will return each of the Code values for which there are no corresponding non-NULL values in CodeResult:
select distinct Code
from CodeResult as CR
where not exists
( select 42 from CodeResult as iCR where iCR.Code = CR.Code and iCR.CodeResult is not NULL );
Counting the rows is left as an exercise for the reader.

SQL Oracle Find Max of count

I have this table called item:
| PERSON_id | ITEM_id |
|------------------|----------------|
|------CP2---------|-----A03--------|
|------CP2---------|-----A02--------|
|------HB3---------|-----A02--------|
|------BW4---------|-----A01--------|
I need an SQL statement that would output the person with the most Items. Not really sure where to start either.
I advice you to use inner query for this purpose. the inner query is going to include group by and order by statement. and outer query will select the first statement which has the most items.
SELECT * FROM
(
SELECT PERSON_ID, COUNT(*) FROM TABLE1
GROUP BY PERSON_ID
ORDER BY 2 DESC
)
WHERE ROWNUM = 1
here is the fiddler link : http://sqlfiddle.com/#!4/4c4228/5
Locating the maximum of an aggregated column requires more than a single calculation, so here you can use a "common table expression" (cte) to hold the result and then re-use that result in a where clause:
with cte as (
select
person_id
, count(item_id) count_items
from mytable
group by
person_id
)
select
*
from cte
where count_items = (select max(count_items) from cte)
Note, if more than one person shares the same maximum count; more than one row will be returned bu this query.

How to join three select queries which has one common column

I have three select queries as below which gives a respective output
select DATE_FORMAT(table1.value_date,'%b')as Month,
DATE_FORMAT(table1.value_date,'%Y') as Year,
table1.open as Open
from index_main as table1
join ( select min(`value_date`) `value_date`
from index_main
group by month(`value_date`), year( `value_date`)
) as table2 on table1.`value_date` = table2.`value_date`
Output columns - Month,year,open
select DATE_FORMAT(table1.value_date,'%b')as Month,
DATE_FORMAT(table1.value_date,'%Y') as Year,
table1.close as Open
from index_main as table1
join ( select max(`value_date`) `value_date`
from index_main group by month(`value_date`), year( `value_date`)
) as table2 on(table1.`value_date` = table2.`value_date`)
Output columns - Month,year,close
select DATE_FORMAT(table1.value_date,'%b')as Month,
DATE_FORMAT(table1.value_date,'%Y') as Year,
max(table1.high) as High
FROM `index_main` as table1
GROUP BY table1.month,table1.year
ORDER BY year(table1.value_date) desc, month(table1.value_date) desc
Output columns - Month,year,high,low
I want to join these three select queries based on the common columns i.e month & year.
My final result should have the following columns - month,year,open,close,high,low.
Try this.
First create 3 views, one with each query (vw1, vw2 and vw3). Then use a query like this:
SELECT vw1.Month, vw1.Year, Open, Close High FROM vw1 LEFT join vw2 on vw1.Year=vw2.Year and vw1.Month=vw2.Month LEFT JOIN vw3 on vw1.Year=vw3.Year and vw1.Month=vw3.Month
Hope this helps you.

MS Access - return values by max date

I'm lost on this one, I'm a bit of a newcomer to Access and SQL, I have scoured the site and Google for the answer to this one.
I have a table with 3 columns containing IDs to other tables and then a date.
Column 1 (RoleID) Column 2 (ActionID) Column 3 (SettingID) Column 4 (Date)
I need to group by Column 1 and Column 2 (so the unique combinations of these). There may be multiple instances with different SettingID, differentiated by a date.
I think a Totals select query does the job, with Group by for Column1 and 2, then using Max for the date column. However I just want the value of Column 3, not a total.
Is there a simple way to do this that I'm missing?
select roleid, actionid, settingid
from your_table t1
inner join
(
select roleid, actionid, max(date) as mdate
from your_table
group by roleid, actionid
) t2 on t1.roleid = t2.roleid
and t1.actionid = t2.actionid
and t1.date = t2.mdate
If this is a really old version of Access then it won't support Subqueries very well
You can work round this by creating a seperate query
select roleid, actionid, max(date) as mdate
from your_table
group by roleid, actionid
Save it as MaxDateQuery or something similar
Then you can use that saved Access query in a subsequent query to get what you wannt
select
your_table.roleid,
your_table.actionid,
your_table.settingid
from your_table
inner join MaxDateQuery
on your_table.roleid = MaxDateQuery.roleid
and your_table.actionid = MaxDateQuery.actionid
and your_table.date = MaxDateQuery.mdate

Select a NON-DISTINCT column in a query that return distincts rows

The following query returns the results that I need but I have to add the ID of the row to then update it. If I add the ID directly in the select statement it will return me more results then I need because each ID is unique so the DISTINCT statement see the line as unique.
SELECT DISTINCT ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
So basically I need to add ucpse.ID in the Select statement while keeping DISTINCT values for MemberID,ProductID and UserID.
Any Ideas ?
Thank you
According to you comment:
If the data has been duplicated 67 times for a given employee with a given product and a given client, I need to keep only one of thoses records. It's not important which one, so this is why I use DISTINC to obtain unique combinaison of given employee with a given product and a given client.
You can use MIN() or MAX() and GROUP BY instead of DISTINCT
SELECT MAX(ucpse.ID) AS ID, ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
UPDATE:
From you comments I think the below query is what you need
DELETE FROM UserCustomerProductSalaryExceptions
WHERE ID NOT IN ( SELECT MAX(ucpse.ID) AS ID
FROM #UserCustomerProductSalaryExceptions
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
HAVING COUNT(ucpse.ID) >= 2
)
If all you want is to delete the duplicates, this will do it:
WITH X AS
(SELECT ID,
ROW_NUMBER() OVER (PARTITION BY MemberID, ProductID, UserID ORDER BY ID) AS DupRowNum<br
FROM UserCustomerProductSalaryExceptions
)
DELETE X WHERE DupRowNum > 1
ID's not necessary - try:
UPDATE uu SET
<your settings here>
FROM UserCustomerProductSalaryExceptions uu
JOIN ( <paste your entire query above here>
) uc ON uc.MemberID=uu.MemberId AND uc.ProductID=uu.ProductId AND uc.UserID=uu.UserId
From the sound of your data structure (which I would STRONGLY advise normalizing as soon as possible), it sounds like you should be updating all the records. It sounds as if each duplicate is important because it contains some information about an employee's relation to a customer or product.
I would probably update all the records. Try this:
UPDATE UCPSE
SET
--Do your updates here
FROM UserCustomerProductSalaryExceptions as ucpse
JOIN
(
SELECT UserID, MemberID, ProductID
FROM UserCustomerProductSalaryExceptions
GROUP BY UserID, MemberID, ProductID
HAVING COUNT(UserID) >= 2
) T
ON ucpse.UserID = T.UserID AND ucpse.MemberID = T.MemberID AND ucpse.ProductID = T.ProductID