Select latest row from a group of options MySQL - mysql

I have a table that contains a set of options and relevant pricing. We have versioning implemented which means that we store several rows for the same option with different timestamps. Everytime we make an update to the pricing, a new row is created with a timestamp.
I am using the query below:
SELECT
localizedOptionID,
uProfileID,
sOptionID,
MAX(datestamp),
localOptionName,
quantities
FROM
localisedProductOptions
WHERE
uProfileID = 2
AND sOptionID in ('BGCD','Q6G1','3BET')
GROUP BY sOptionID
ORDER BY MAX(datestamp)
It seems to be returning only one version of each row, but unfortunately it does not seem to be the latest.
Can anyone help me setting up the query? All the data is contained within one single table, so I am not using any join.

You can try the below mentioned query to get desire data
select localizedOptionID, uProfileID,sOptionID, datestamp,localOptionName,
quantities from localisedProductOptions WHERE uProfileID = 2 AND sOptionID in
('BGCD','Q6G1','3BET') and datestamp in(select MAX(datestamp) from
localisedProductOptions where uProfileID = 2 AND sOptionID in
('BGCD','Q6G1','3BET') GROUP BY sOptionID);

Related

How to limit Row result on query when no Primary Key in table

I'm new to SQL as for over 20 years I haven't touched a single code line, so it feels like starting over.
I have a database with two tables, one for Projects, and another one for the Milestones. What I'm trying to achieve is to have a query that will retrieve the latest Milestone logged for each project. That way I can build a report with one project line with the latest update only.
I've managed to build the query to retrieve 1 (One) Milestone Record for each project. However when I've logged more than one update for the same date, the query returns all of them. I've tried to utilize the rowid, but it didn't work.
Here my sample tables:
And the query I've tried to run that currently retrieves more than 1 record when milestone created the same date.
select PROJECT_DATA.PARTNER_NAME as PARTNER_NAME,
PROJECT_DATA.SOLUTION_STATUS as SOLUTION_STATUS,
PROJECT_DATA.STRATEGY_MANAGER as STRATEGY_MANAGER,
PROJECT_DATA.SOLUTION_TYPE as SOLUTION_TYPE,
PROJECT_DATA.INTEGRATION_METHOD as INTEGRATION_METHOD,
PROJECT_MILESTONE.MILESTONE as MILESTONE,
PROJECT_MILESTONE.COMPLETED_ON as COMPLETED_ON,
PROJECT_MILESTONE.NOTES as NOTES
from PROJECT_DATA JOIN PROJECT_MILESTONE PROJECT_MILESTONE ON PROJECT_DATA.ID=PROJECT_MILESTONE.PROJECT_ID
where PROJECT_MILESTONE.COMPLETED_ON = (Select MAX (PROJECT_MILESTONE.COMPLETED_ON)
FROM PROJECT_MILESTONE
WHERE PROJECT_DATA.ID=PROJECT_MILESTONE.PROJECT_ID)
Any help on how to limit the query result to just 1 (newest one) when logged in the same date, will be extremely helpful.
Assuming that Completed on has the time as well along with the date, all you need to do is select top 1 in the ORDER BY DESC
Something like
select top 1 PROJECT_DATA.PARTNER_NAME as PARTNER_NAME,
PROJECT_DATA.SOLUTION_STATUS as SOLUTION_STATUS,
PROJECT_DATA.STRATEGY_MANAGER as STRATEGY_MANAGER,
PROJECT_DATA.SOLUTION_TYPE as SOLUTION_TYPE,
PROJECT_DATA.INTEGRATION_METHOD as INTEGRATION_METHOD,
PROJECT_MILESTONE.MILESTONE as MILESTONE,
PROJECT_MILESTONE.COMPLETED_ON as COMPLETED_ON,
PROJECT_MILESTONE.NOTES as NOTES
from PROJECT_DATA JOIN PROJECT_MILESTONE PROJECT_MILESTONE ON
PROJECT_DATA.ID = PROJECT_MILESTONE.PROJECT_ID
order by COMPLETED_ON DESC
Also, the joining condition has to be specified after the "ON" in joins and then you can use where condition to filter out the data

Analysing multiple rows to determine one status

In one of my tables, some customers have multiple lines - this could be due to re-visits from technicians etc. What I want to do is for each customer ID, analyse whether a re-vist has taken place and place a marker against their name.
I have tried to combine an if/in statement that analyses the max/min visit dates for each customert ID. So if the max>min its classed as a "re-visit", however, i keep getting a syntax error.
Can someone help?
This is a job for two SQL queries:
1st query:
SELECT customerID, count(customerID) as visitCount
FROM tableOfInterest
GROUP BY customerID
2nd query uses first query:
UPDATE customerManifest INNER JOIN queryAbove ON queryAbove.customerID = customerManifest.customerID
SET customerManifest.multipleVisitIndicatorField to queryAbove.visitCount

MySQL joined query with max dates from two tables

I got two tables that contain date and time stamps and trying to extract records by the latest date in both.
Table 1 (sessions):
id---login_date------------ip
01---2014-01-02 23:58:40---127.0.0.1
03---2014-01-01 13:20:16---127.0.0.1
01---2014-01-01 17:06:15---127.0.0.1
02---2013-12-30 14:34:39---127.0.0.1
*also multiple other non-date columns which are not playing part in this solution
Table 2 (reminders):
id---last_reminder---------next_reminder
03---2013-12-29 22:50:18---2014-01-07 22:50:18
02---2014-01-01 15:15:15---2014-01-09 15:15:15
02---2013-11-16 08:54:23---2013-11-23 08:54:23
Now this is the way I get all the latest logins from the first table for each user ID:
SELECT a.id, a.login_date
FROM sessions a
WHERE a.login_date = (
SELECT max(login_date) as login_date
FROM sessions
WHERE id = a.id
LIMIT 1
)
GROUP BY a.id
What I would like to get is not only the last login date for each user ID, but also the last sent reminder (if any). As this involves selecting two max dates I never get correct results.
Desired Result:
id---login_date------------last_reminder---------next_reminder------
01---2014-01-02 23:58:40---NULL------------------NULL---------------
02---2013-12-30 14:34:39---2014-01-01 15:15:15---2014-01-09 15:15:15
03---2014-01-01 13:20:16---2013-12-29 22:50:18---2014-01-07 22:50:18
Would anybody please help me out with this.
Thanks,
Simon
////////////////////////UPDATED 2014-01-04 WITH EXTRA COLUMNS////////////////////////////
Based on the request the above table structure was updated to contain extra fields, required to produce correct query results.
*note that next_reminder field will always have a value as it's calculated based on the last reminder value. The query will eventually check whether the next reminder is within certain timeframe too.
P.S. StackOverflow is full of very good answers when only one table contains the date and time stamp (from which I have built what I have got so far), however I could not locate any similar examples that would involve joining two tables and selecting max dates from each.
if you have only two columns per table, you can directly join it and use MAX() to get the latest record for each ID.
SELECT a.id,
MAX(login_date) latest_login_date,
MAX(last_reminder) latest_reminder
FROM sessions a
LEFT JOIN reminders b
ON a.id = b.id
GROUP BY a.id
SQLFiddle Demo

Invalid results returning from a multi-table SELECT Statement

I have a Database with the following structure:
http://i.imgur.com/DFZz3Py.png
I'm trying to run a select statement, getting information from multiple tables, however it keeps bringing me duplicate results. The statement I'm using is:
SELECT StockReceipts.StockID, StockReceipts.Quantity, StockPriceHistory.Price
FROM StockReceipts,StockPriceHistory,Receipts
WHERE (Receipts.ReceiptID = 1) AND (Receipts.OrderDate BETWEEN StockPriceHistory.DateStart AND StockPriceHistory.DateEnd)
And the results i'm getting are:
http://i.imgur.com/2ZrgYyZ.png
What I actually want is matching rows from the stockreceipts table,
but with the price for each item of stock (the price that was within the date & time of ordering - OrderDate taken from the Receipts table) as well, taken from the StockPriceHistory table. I don't understand why it's making up duplicate/incorrect rows when there are only two rows in the StockReceipts table for that receipt.
Can anyone help? Thanks
SELECT
SR.StockID,
SR.Quantity,
SPH.Price
FROM
Receipts R
JOIN StockReceipts SR
on R.ReceiptID = SR.ReceiptID
JOIN StockPriceHistory SPH
on SR.StockID = SPH.StockID
WHERE
R.ReceiptID = 1
AND R.OrderDate BETWEEN SPH.DateStart AND SPH.DateEnd
You had no JOIN conditions between the tables leaving it a Cartesian result... For every record in one, grabbed entries from all other table rows.

Join on 3 tables insanely slow on giant tables

I have a query which goes like this:
SELECT insanlyBigTable.description_short,
insanlyBigTable.id AS insanlyBigTable,
insanlyBigTable.type AS insanlyBigTableLol,
catalogpartner.id AS catalogpartner_id
FROM insanlyBigTable
INNER JOIN smallerTable ON smallerTable.id = insanlyBigTable.catalog_id
INNER JOIN smallerTable1 ON smallerTable1.catalog_id = smallerTable.id
AND smallerTable1.buyer_id = 'xxx'
WHERE smallerTable1.cont = 'Y' AND insanlyBigTable.type IN ('111','222','33')
GROUP BY smallerTable.id;
Now, when I run the query first time it copies the giant table into a temp table... I want to know how I can prevent that? I am considering a nested query, or even to reverse the join (not sure the effect would be to run faster), but that is well, not nice. Any other suggestions?
To figure out how to optimize your query, we first have to boil down exactly what it is selecting so that we can preserve that information while we change things around.
What your query does
So, it looks like we need the following
The GROUP BY clause limits the results to at most one row per catalog_id
smallerTable1.cont = 'Y', insanelyBigTable.type IN ('111','222','33'), and buyer_id = 'xxx' appear to be the filters on the query.
And we want data from insanlyBigTable and ... catalogpartner? I would guess that catalogpartner is smallerTable1, due to the id of smallerTable being linked to the catalog_id of the other tables.
I'm not sure on what the purpose of including the buyer_id filter on the ON clause was for, but unless you tell me differently, I'll assume the fact it is on the ON clause is unimportant.
The point of the query
I am unsure about the intent of the query, based on that GROUP BY statement. You will obtain just one row per catalog_id in the insanelyBigTable, but you don't appear to care which row it is. Indeed, the fact that you can run this query at all is due to a special non-standard feature in MySQL that lets you SELECT columns that do not appear in the GROUP BY statement... however, you don't get to select WHICH columns. This means you could have information from 4 different rows for each of your selected items.
My best guess, based on column names, is that you are trying to bring back a list of items that are in the same catalog as something that was purchased by a given buyer, but without any more than one item per catalog. In addition, you want something to connect back to the purchased item in that catalog, via the catalogpartner table's id.
So, something probably akin to amazon's "You may like these items because you purchased these other items" feature.
The new query
We want 1 row per insanlyBigTable.catalog_id, based on which catalog_id exists in smallerTable1, after filtering.
SELECT
ibt.description_short,
ibt.id AS insanlyBigTable,
ibt.type AS insanlyBigTableLol,
(
SELECT smallerTable1.id FROM smallerTable1 st
WHERE st.buyer_id = 'xxx'
AND st.cont = 'Y'
AND st.catalog_id = ibt.catalog_id
LIMIT 1
) AS catalogpartner_id
FROM insanlyBigTable ibt
WHERE ibt.id IN (
SELECT (
SELECT ibt.id AS ibt_id
FROM insanlyBigTable ibt
WHERE ibt.catalog_id = sti.catalog_id
LIMIT 1
) AS ibt_id
FROM (
SELECT DISTINCT(catalog_id) FROM smallerTable1 st
WHERE st.buyer_id = 'xxx'
AND st.cont = 'Y'
AND EXISTS (
SELECT * FROM insanlyBigTable ibt
WHERE ibt.type IN ('111','222','33')
AND ibt.catalog_id = st.catalog_id
)
) AS sti
)
This query should generate the same result as your original query, but it breaks things down into smaller queries to avoid the use (and abuse) of the GROUP BY clause on the insanlyBigTable.
Give it a try and let me know if you run into problems.