Here is the original question:
There is a table stockprices, which contains information about trades of one company's stock. It has two columns: timestamp and price. They represent the time when a trade happened and the price of the sale. The natural order of records in the table is random and is not sorted by timestamp.
You add another column (let's call it delta) where you intend to store the difference between the current transaction price and the price of the previous transaction time-wise.
Write a single SQL statement, which will calculate the price difference and fill the column delta with it in all rows.
I write the sql as below to run on mysql, but seems current is not supported on mysql, and i can't move on, the following is the one i wrote till now to calculate the difference between the current transaction price and the price of the previous transaction time-wise:
SELECT
[current].timestamp,
[current].price,
ISNULL([next].price, 0) - [current].price
FROM
stockprice AS [current]
LEFT JOIN
stockprice AS [next]
ON [next].timestamp = (SELECT MIN(timestamp) FROM stockprice WHERE timestamp > [current].timestamp)
You're using square brackets as identifier delimiters. This syntax works only in Microsoft SQL Server and Sybase. You should use syntax that works in MySQL, which is back-quotes by default and double-quotes if you enable ANSI_QUOTES mode.
See my answer to Do different databases use different name quote?
Related
I have a pricing history table with half a billion records. It is formatted like this:
Id, sku, vendor, price, datetime
What I want to do is get average price of all products by vendor for a certain date range. Most products are updated once every 3 days, but it varies.
So, this is the query I want to run:
SELECT
avg(price)
FROM table
WHERE
vendor='acme'
AND datetime > '12-15-2014'
AND datetime < '12-18-2014'
GROUP BY sku
This 3 day range is broad enough that i will for sure get at least one price sample, but some skus may have been sampled more than once, hence group by to try and get only one instance of each sku.
The problem is, this query runs and runs and doesn't seem to finish (more than 15 minutes). There are around 500k unique skus.
Any ideas?
edit: corrected asin to sku
For this query to be optimized by mysql you need to create a composite index
(vendor, datetime, asin)
IN THIS PARTICULAR ORDER (it mattters)
It also worth trying creating another one
(vendor, datetime, asin, price)
since it may perform better (since it's a so called "covering index").
The indexes with other order, like (datetime, vendor) (which is suggested in another answer) are useless since the datetime is used in a range comparison.
Few notes:
The index will be helpful if only the vendor='acme' AND datetime > '12-15-2014' AND datetime < '12-18-2014' filter condition covers a small part of the whole table (say less than 10%)
Mysql does not support dd-mm-yyyy literals (at least it's not documented, see references) so I assume it must be yyyy-mm-dd instead
Your comparison does not cover the first second of the December 15th, 2014. So you probably wanted datetime >= '2014-12-15' instead.
References:
http://dev.mysql.com/doc/refman/5.6/en/range-optimization.html
http://dev.mysql.com/doc/refman/5.6/en/date-and-time-literals.html
You need an index to support your query. Suggest you create an index on vendor and datetime like so:
CREATE INDEX pricing_history_date_vendor ON pricing_history (datetime, vendor);
Also, I assume you wanted to group by sku rather than undefined column asin.
Not to mention your non-standard SQL date format MM-dd-yyyy as pointed out by others in comments (should be yyyy-MM-dd).
SO I have to list the names of anyone in the tenant family who is older than the tenant itself. There are two tables. Tenant and tenant_family. I have tried comparing the two dates to see which DOB in the tenant_family table is less than (meaning they would be older) the DOB in the tenant table.
This is what I have so far but it appears to be wrong. Can someone direct me towards a way of getting the right output?
SELECT DISTINCT tenant_family.name
FROM TENANT_FAMILY, tenant
WHERE tenant_family.dob < tenant.TENANT_DOB;
Use the DATE function to extract the date part of your query for comparison like:
select distinct tenant_family.name from TENANT_FAMILY, tenant where DATE(tenant_family.dob) < DATE(tenant.TENANT_DOB);
In case your dob and TENANT_DOB are not stored as the DATE data type in your database or they are stored as DATETIME then you might extract only the date part using the function:
select distinct tenant_family.name from TENANT_FAMILY, tenant where date_format(tenant_family.dob,"%y-%m-%d") < date_format(tenant.TENANT_DOB,"%y-%m-%d);
This should give you the correct results after comparison.
I have a database that uses a unique ID for each transaction. The transaction ID is the last two digits of a year followed by a four digit sequential number (eg. 0100 to 9999). That number resets back to 0100 at the start of each year. Not all numbers are used each year. Example, the last transaction in 2012 was 12-0409, in 2011 it was 11-0500. These numbers are not currently generated in the database but are created manually. I am in the process of getting them to switch to using automation but in the meantime I have to create patches to fix errors.
In the database, I have one table and one query. The query ([Offer Check]) lists the Transaction ID ([HL#]) and shows just the last four in two formats, one as a number format ([NumList]) and one as a text format ([TextList]). The table is a basic table that lists all the numbers between 0100 and 9999. I am trying to create a query that allows me to identify which Transaction IDs are missing, i.e. I have 13-0250 and 13-0252 but not 13-0251. I can create the query that identifies which numbers are missing, however it also lists all the numbers past the latest Transaction ID. How can I limit the query to the current maximum transaction ID #?
This is what I have so far.
SELECT YearlyOfferIds.YOID
FROM
YearlyOfferIds
LEFT JOIN [Offer Check]
ON YearlyOfferIds.[YOID] = [Offer Check].[TextList]
WHERE ((([Offer Check].TextList) Is Null));
And I'm trying to add or something that does the same thing.
SELECT Max([Offer Check].NumList) AS MaxOfNumList
FROM [Offer Check];
Your second query, SELECT Max(..., can be translated into a DMax expression.
DMax("NumList", "Offer Check")
My hunch is you can use that DMax in your first query's WHERE clause to limit the rows returned from YearlyOfferIds. Unfortunately, I don't know the name of the YearlyOfferIds field which you want to compare with the maximum [Offer Check].NumList. So I'll just call that field some_field.
WHERE
YearlyOfferIds.some_field <= DMax("NumList", "Offer Check")
AND [Offer Check].TextList Is Null
I want to write 1 SQL syntax that will place current transaction in group. This transaction had to be done within last 60 seconds.
Grouping current transaction with other existing transactions is done by assigning group id number (GRID) that is copied from other transaction also performed within a last minute.
In other words:
purchase is done and SQL script will look for other purchases that has been done within last minute and if found it will take group number from found row and assign to current purchase, so in this case every purchase made within a minute will find itself in a group.
This is the update statement below I have composed
UPDATE TRANSACTIONS
SET GRID=(SELECT G FROM
(SELECT GRID AS G
FROM TRANSACTIONS
WHERE CUST_ID='123ID'
AND STAMP+60>UNIX_TIMESTAMP()
LIMIT 1)
AS t),
STAMP=UNIX_TIMESTAMP()
WHERE CUST_ID='123ID'
AND STAMP+60>UNIX_TIMESTAMP();
However this always returns number of updated rows, even if row which exists is only the one is due to be updated, or the other row that was found has no group number assigned yet. Which is obvious as it updates with whatever value was found in subquery. If nothing found it will update with empty value.
There are 2 solutions I am interested in:
I want this script to stop performing update (by condition) if found (from the sub query) value is basically empty.
or
I want to insert condition that if subquery returns empty value, the fix string of characters will be inserted instead.
After a while of exploring my issue I have come to solution.
The following MySQL syntax serves what I want.
Please note very interesting MySQL function IFNULL(). Can be very handy!
UPDATE TRANSACTIONS
SET GRID=(SELECT G FROM
(SELECT IFNULL(GRID, 'NO ID') AS G
FROM TRANSACTIONS
WHERE CUST_ID='123ID'
AND STAMP+60>UNIX_TIMESTAMP()
LIMIT 1)
AS t),
STAMP=UNIX_TIMESTAMP()
WHERE CUST_ID='123ID'
AND STAMP+60>UNIX_TIMESTAMP();
I have a table lead and there is a field called added_on (datatype timestamp), I want to to fetch only the leads which are interested in a particular product and the reports should come monthly.
interested_in is a field in the lead table where the interested product's id will be stored as a comma separated values.
and $prod_id is stored with a product id which has to be checked.
the below query works fine just to fetch out the leads which are interested in a particular product. but i want the results to come month by month.
select*from lead where find_in_set('$prod_id',interested_in)
Please guide me what i have to do to achieve that
TRY
WHERE MONTH(added_on) = $giveMonthNumber
OR
WHERE MONTHNAME(added_on) = $givenMonthName;
Reference :
MySQL date time functions
Do this:
select * from lead where find_in_set('$prod_id',interested_in) group by added_on