SQL - Getting more data with a GROUP BY - sql

Hoping someone can help me out with this.
Lets say I have a table called incoming_data with 4 columns:
primary_key_id
serial_number
counter
selected_color
I get data from a source that fills this table. The primary key has its identity
turned on so it is not repeating. I will get duplicate serial numbers with different selected colors.
The counter is ever increasing coming from the device.
So what I want to do is select all the data I received today, group the data by serial number and only get the record
with the highest counter value.
Simple:
SELECT serial_number, MAX(counter)
FROM incoming_data
GROUP BY serial number
This works perfectly, except that I want to do something with the color information
that I received.
If I add color to the select, then I get ALL the records since all
the colors I received that day are different. That wont work.
If I could get the primary_key_id of the record then I could just
query for the color but this doesn't work either since each primary_key_id
value is different I get them all.
Any suggestions on a better technique for doing this?
Thanks!

Extract the relevant key, then join back to get "non key".
This works in MS SQL Server and later Sybase.
SELECT
i.serial_number, i.counter, i.selected_color
FROM
(
SELECT serial_number, MAX(counter) AS maxc
FROM incoming_data
GROUP BY serial number
) max
JOIN
incoming_data i ON max.serial_number = i.serial_number AND max.maxc = i.counter

EDIT: t odeal with cases where multiple records have same serial number and max counter value.. This will extract the one of those multiples with the biggest primary_key_id
Select * From incoming_data
Where primary_key_id In
(Select Max(primary_key_id) From incoming_data I
Where Counter =
(Select Max(counter) From incoming_data
Where SerialNumber = I.SerialNumber)
Group By SerialNumber)

Hi I think this might do what you want?
SELECT selected_color, serial_number, counter
FROM incoming_data
GROUP BY serial_number
ORDER BY counter DESC
LIMIT 1;

If you don't need the exact color from the query, but could parse it afterwards, try this:
SELECT serial_number, MAX(counter), MAX( CONCAT(counter, ':', selected_color) )
FROM incoming_data
GROUP BY serial number

I am trying to get the max numbers from two joined tables. I tried to use DISTINCT to avoid repeatative numbers, but failed. Then I found the following query and works perfect on single table, but I failed to have it worked on joined two tables.
How to implement the following query on my query:
select top 10 ConsumptionKWH
from PeriodicConsumptions
group by ConsumptionKWH
order by min(ConsumptionKWH) asc
Needed on:
" SELECT * FROM " & _
" (SELECT Distinct top 10 " & _
" PeriodicConsumptions.ConsumptionKWH, " & _
" MeterReadings.MeterNo, " & _
" MeterReadings.LastKWH," & _
" MeterReadings.AccountNo, " & _
" MeterReadings.MultiplyFactor," & _
" MeterReadings.LastReading, " & _
" MeterReadings.ThisMonthReading," & _
" MeterReadings.NumberofDays," & _
" MeterReadings.ReadingGYear, " & _
" MeterReadings.ReadingGMonth, " & _
" MeterReadings.ReadingDate " & _
" FROM MeterReadings, PeriodicConsumptions" & _
" Where MeterReadings.AccountNo = PeriodicConsumptions.AccountNo " & _
" and MeterReadings.ReadingGYear =PeriodicConsumptions.ConsumptionYear " & _
" and MeterReadings.ReadingGMonth =PeriodicConsumptions.ConsumptionMonth " & _
" and MeterReadings.ReadingDate = PeriodicConsumptions.FromDate " & _
" ORDER BY PeriodicConsumptions.ConsumptionKWH desc) as t " & _
" ORDER BY ConsumptionKWH asc"
Thanks

Related

Finding/Marking Duplicate Values using SQL

I am trying to update a column in my table to specify if the record is a duplicate or not. To do this I added a field called 'DuplicateRecord'.
I can't use the query wizard in access as the duplicate option in this only allows for 10 fields to be checked as a duplicate and my table has more than 10 fields.
The below code works for me:
Call Module1.RunSQL("UPDATE myTable " & _
"SET myTable.DuplicateRecord = TRUE " & _
"WHERE myTable.[CompanyID] IN (" & _
"SELECT * FROM " & _
"(SELECT myTable.[CompanyID] " & _
"FROM myTable " & _
"GROUP BY myTable.[CompanyID] " & _
"HAVING COUNT(*) > 1 ) T1 ) ")
However this code just runs off one field and I need it to run off all fields in the table (there are about 15 fields).
As a test I tried using two fields to see if I could get this working using the following:
Call Module1.RunSQL("UPDATE myTable " & _
"SET myTable.DuplicateRecord = TRUE " & _
"WHERE myTable.[CompanyID] AND myTable.[Product] IN (" & _
"SELECT * FROM " & _
"(SELECT myTable.[CompanyID], myTable.[Product], COUNT(*) " & _
"FROM myTable " & _
"GROUP BY myTable.[CompanyID], myTable.[Product] " & _
"HAVING COUNT(*) > 1 ) T1 ) ")
However I get an error message saying "Run-time error '3306' You have written a subquery that can return more than one field without using the EXISTS reserved word in the main query's FROM clause. Revise the SELECT statement of the subquery to request only one field."
I've tried googling the error but I can't seem to solve it as I don't fully understand it.
Does anyone know how I can apply the logic of testing for duplicates? Is there an easier way to do this then how I am currently trying? I will need to do this for the full record (15 fields), so I am a bit conscious that the way I am currently attempting this might not be the best fit.

SQL Server Join Tables By Combining 2 Columns

This sounds ridiculously easy but I've tried so many different approaches. This query is just set up weird and I'm trying to JOIN it but there's not a common column I can do that with. There is, however, a LastFirst column (consists of LastName then FirstName) written in the context of DOE, JOHN. Then on the columns I'm trying to join that with it's just FirstName (John) and LastName (Doe).
I'm actually trying to select data from 4 tables that all are returning 1 row. These 2 tables can be joined:
SELECT
RIFQuery.*,
_Employee.EmployeeLastName + ', ' + _Employee.EmployeeFirstName AS EmployeeLastFirst,
_Employee.EmployeeTitle, _Employee.Phone As EmployeePhone,
_Employee.EmailAddress As EmployeeEmailAddress
FROM
RIFQuery
INNER JOIN
_Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE
RIFQuery.Autonumber = 1
This one has nothing to join with so I'll probably union it and null remaining columns:
SELECT *
FROM tblOrganization
This is the table that contains LastName and FirstName that I'm trying to join with RIFQuery.LastFirst:
SELECT
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM
_Clients
WHERE
_Clients.LASTNAME = left(RIFQuery.LastFirst, len(RIFQuery.LastFirst)-CHARINDEX(',', REVERSE(RIFQuery.LastFirst)))
AND _Clients.FIRSTNAME = ltrim(substring(RIFQuery.LastFirst, len(RIFQuery.LastFirst)-CHARINDEX(',', REVERSE(RIFQuery.LastFirst))+2, len(RIFQuery.LastFirst)))
In that WHERE statement the code will split the LastFirst column and get the row by searching their LastName and FirstName. I'm wondering if there's a way I can write that into a JOIN? Otherwise I can probably UNION and null remaining columns but it will look very ugly.
UPDATE
I tried 2 suggestions from here and both result in a syntax error. I forgot to mention that I'm executing this code inside Microsoft Access VBA and trying to retrieve a DAO.RecordSet. I had to remove some table names in the SELECT statement to get past a syntax error from there, so maybe I should update the question to reflect MS ACCESS and not SQL Server, although only the query is the only pure Access object and the rest are linked ODBC tables to SQL Server.
UPDATE
Just one of those issues where I can't sleep until it's fixed and will obsess until it is. If I take out all _Employee references (from SELECT and JOIN statements), it wants to work but errors about too few parameters. I just now know this is related to _Employee. Getting different results from applying parentheses and just hoping I'll get lucky and hit on it.
The error is caused by this line:
INNER JOIN [_Employee] ON [_Employee].[AutoNumber] = [RIFQuery].[CreatedBy]
I get this error:
"Syntax error (missing operator) in query expression".
As seen in this screenshot:
Here's my latest query I'm playing with, minus the parentheses:
str = "SELECT [RIFQuery].*, " & vbCrLf & _
" ([_Employee].[EmployeeLastName] & ', ' & [_Employee].[EmployeeFirstName]) AS [EmployeeLastFirst], " & vbCrLf & _
" [_Employee].[EmployeeTitle], " & vbCrLf & _
" [_Employee].[Phone] AS [EmployeePhone], " & vbCrLf & _
" [_Employee].[EmailAddress] AS [EmployeeEmailAddress], " & vbCrLf & _
" [_Clients].[Gender] AS [ClientGender], " & vbCrLf & _
" [_Clients].[DOB] AS [ClientDOB], " & vbCrLf & _
" [_Clients].[SSN] AS [ClientSSN] " & vbCrLf & _
"FROM [_Clients] " & vbCrLf & _
" INNER JOIN [RIFQuery] ON [RIFQuery].[LastFirst] = [_Clients].[LASTNAME] & ', ' & [_Clients].[FIRSTNAME] " & vbCrLf & _
" INNER JOIN [_Employee] ON [_Employee].[AutoNumber] = [RIFQuery].[CreatedBy] " & vbCrLf & _
"WHERE [RIFQuery].[Autonumber] = 1;"
For debugging purposes, if I remove those last 2 lines and the _Employee SELECT statements, it'll process the query without a problem. If anyone has any ideas just let me know.
I was focused on that RIFQuery JOIN statement being the culprit for the longest time but I've found that simply is not the issue any more. With that said, this thread has been essentially solved and I appreciate the help.
MS Access is using a slightly different syntax than SQL Server when it comes to using more than one JOIN. You could leave out the JOIN with the _Clients (making it a cross join) and move that condition to the WHERE clause, which would make the query look like this (and which would allow you to display the design window for the query without any problem)
SELECT RIFQuery.*,
EmployeeLastName + ', ' + EmployeeFirstName As EmployeeLastFirst,
EmployeeTitle, Phone As EmployeePhone, EmailAddress As EmployeeEmailAddress,
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM _Clients, RIFQuery INNER JOIN _Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE RIFQuery.LastFirst = _Clients.LASTNAME & ", " & _Clients.FIRSTNAME;
Instead of assembling the query string in VBA just for being able to change the parameter value, I suggest to save the following query as an Access object (maybe qryRIF):
PARAMETERS lgRIF Long;
SELECT RIFQuery.*,
EmployeeLastName + ', ' + EmployeeFirstName As EmployeeLastFirst,
EmployeeTitle, Phone As EmployeePhone, EmailAddress As EmployeeEmailAddress,
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM _Clients, RIFQuery INNER JOIN _Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE RIFQuery.LastFirst = _Clients.LASTNAME & ", " & _Clients.FIRSTNAME
AND RIFQuery.Autonumber = [lgRIF];
In your VBA code, you can use code like the following to grab the QueryDef object, assign the parameter value and open a recordset:
With CurrentDb.QueryDefs!qryRIF
!lgRIF = lgRIF
With .OpenRecordset()
' ... your code ...
.Close
End With
.Close
End With

SQL - Get the most recent data

Hi guys I hope you can help me!
I have done this piece of code here:
" SELECT distinct left(ut.Text,27) " & _
" FROM [MyDataBase].[dbo].[table1] ut, dbo.table2 u " & _
" WHERE ut.table1 in (select unitid from dbo.table2 where serialno like '" & CStr(Right(Sheet1.Cells(i, 3), 8)) & "' ) " & _
" AND ut.text like 'EPP:%' " & _
" AND u.table2 = ut.table1 " & _
" ORDER BY 1 "
It works perfectly! What it does?
I have a sheet like this:
ORDER PID SERIAL
3033421 6625MC3209 13-49026969
3033421 6625MC3209 13-49027001
It gets the information on the third column and uses it to search and paste the data from the database into the fourth column.
My problem is: the query pastes the first information it gets and actually I need it to get the last information (or to be more precise the latest information added). To illustrate:
ORDER PID SERIAL EPP
3033421 6625MC3209 13-49026969 123456789 2015-01-25
3033421 6625MC3209 13-49026969 987654321 2015-03-25
My query is pasting the data that dates 2015-01-25 and I need it to paste the data that dates 2015-03-25 (that is the most recent one).
Hope it is clear :P
Thanks in advance!

SQL ORDER BY on Update- update last record with condition

I am trying to update the last record of table Log (the field with the latest TimeAccessed) given that TimeExited is null, and the computername is the same as the "cm" parameter. I have this but get error, "missing semicolon at end of sql statement"
what is wrong??
dbs.Execute "UPDATE Log " _
& "SET TimeExited = " & Format(CloseTime, "\#hh:mm:ss AMPM\#") _
& " WHERE TimeExited is NULL AND ComputerName = '" & cm & "'" _
& " ORDER BY TimeAccessed DESC" _
& " LIMIT 1; "
nothing wrong with first 2 lines, work perfectly fine, it's the last two that give problems
Access SQL doesn't use LIMIT n it uses TOP n, and as mentioned in the other question cited in the comments to your question, you aren't allowed to use TOP in the way you've described. Instead, you'll need to do something along these lines:
UPDATE Log
SET TimeExited = CloseTime
WHERE TimeExited IS NULL
AND ComputerName='r2d2'
AND TimeAccessed IN
(
SELECT TOP 1 TimeAccessed
FROM Log
WHERE TimeExited IS NULL
AND ComputerName='r2d2'
ORDER BY TimeAccessed DESC
)

T-SQL - Filtering records based on a date

I am writing SQL Server queries and need a solution for how to filter the rows that are returned properly.
The basic setup is as follows - I am selecting a bunch of records from a table based primarily on an identifier. So, for a given identifier there might be 100 records that are returned initially. Within these 100 records, however, there are a number of them that need to be deleted - not because they are duplicates, but because one is newer than the other. So I essentially just need a way to further filter the results based on whichever record was created/modified most recently.
I know that ideally, these "old" records should not be in the database, but I don't have control over that. What is happening is essentially people are updating the entries over time to reflect new information, but rather than editing the "old" entry, a new one gets entered each time. Thus, there might be 3 entries for a given identifier, but I only need the one that was most recently entered.
Is there an easy way to do this in the T-SQL query string? It would be similar to the "Last of" function in Access queries. I do have a properly formatted date column for each record.
Thanks!
My query string so far (excuse the VB syntax):
"SELECT *" & _
"FROM Performance_Override " & _
"WHERE ([Deal_Name] = " & "'" & Range("ID").value & "'" & " or" & _
" [UNIQUE_ID] LIKE " & "'" & "%SPLIT_LOAN%" & "')" & " AND" & _
" ([Scenario] = " & "'" & "BASE" & "')" & _
"ORDER BY [Date] ASC; "
Select is
select ID, max(datefield)
from table
group by ID
Do you just need a select or do you want to actually delete the old entries?
WITH TableTop AS
(
SELECT ID, User, OrderDate
ROW_NUMBER() OVER (ID BY OrderDate DESC) AS RowNumber
FROM Table
)
SELECT ID, User, OrderDate
FROM TableTop
WHERE RowNumber = 1;