Getting latest quote data for stock - mysql

I am collecting quote data and chose opt_ticker and quoteTimeStamp as the primary key so that I can store unique quotes over time. I now want to create a view where I can see the latest quote for each opt_ticker (data base has other opt_tickers with unique quotes as well). Basically want to see the latest quote for each stock/option.
In the example above, I want to get that last row as it is the latest timestamp for that particular contract.
I thought this query would do the trick but mysql complains that I need to do a group by.
select symbol,opt_ticker,ask,bid,exp,strike,type,max(quoteTimeStamp)
from optionquotes
group by opt_ticker
21:36:42 select symbol,opt_ticker,ask,bid,exp,strike,type,max(quoteTimeStamp) from optionquotes group by opt_ticker,symbol LIMIT 0, 1000 Error Code: 1055. Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'od2.optionquotes.ask' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by 0.000 sec
Here my server info if it helps
Server
Product: (Ubuntu)
Version: 5.7.30-0ubuntu0.16.04.1
Connector
Version: C++ 8.0.20
This sounds so easy but I am having the toughest time figuring this out, thank you in advance.

In MySQL 5.x you can do:
select *
from optionquotes
where (opt_ticker, quoteTimeStamp) in (
select opt_ticker, max(quoteTimeStamp)
from optionquotes
group by opt_ticker
)
In MySQL 8.x you can do:
select *
from (
select *,
row_number() over(partition by opt_ticker order by quoteTimeStamp desc) as rn
from optionquotes
) x
where rn = 1

Just to round out the answers, here is a canonical way to do this using a join:
SELECT oq1.*
FROM optionquotes
INNER JOIN
(
SELECT opt_ticker, MAX(quoteTimeStamp) AS maxQuoteTimeStamp
FROM optionquotes
GROUP BY opt_ticker
) oq2
ON oq1.opt_ticker = oq2.opt_ticker AND
oq1.quoteTimeStamp = oq2.maxQuoteTimeStamp;

Related

Rewrite the SQL in version 5.7

I have a following SQL which works in mysql version 5.6 but is breaking in mysql version 5.7.x.
SELECT * FROM (SELECT * FROM photos WHERE photoable_type = 'Mobilehome'
AND photoable_id IN (SELECT id FROM mobilehomes WHERE
mobilehomes.community_id = 1) AND photos.image_file_size IS NOT NULL
AND photos.is_published IS TRUE ORDER BY photos.priority ASC) AS tmp_table
GROUP BY photoable_id
It's throwing me following error:
Expression #1 of SELECT list is not in GROUP BY clause and contains
nonaggregated column 'tmp_table.id' which is not functionally
dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
In this case or you change the sql mode for instrcut the db to work as mysql 5.6 version or you can adeguate your query to the new behavior
In this second case
If you use group by whithout aggregation function this mean that for all the column different from photoable_id you accept casual result
This mean that you could, probably, also accepted an aggregated result based greagtion function eg: on min() or max ()
assuming your tables containg col1, col2, .. the you must declare explicitally the column you need
SELECT photos.photoable_id, min(col1), min(col2),....
FROM photos
INNER JOIN mobilehomes ON mobilehomes.community_id = 1
AND photos.photoable_type = 'Mobilehome'
AND photos.photoable_id = mobilehomes.id
AND photos.image_file_size IS NOT NULL
AND photos.is_published IS TRUE
GROUP BY photos.photoable_id
ORDER BY photos.priority ASC
Looking to your code seems also that you could avoid the subquery

How to do two different count in one sql

How can do two different count in one table?
The two different count functions count different columns.
Simplified Table:
id,creatorId,resolverId
'1','1','2'
'2','1','2'
'3','2','2'
'4','2','1'
What I want to do is putting the creatorId,COUNT(creatorId),resolverId,COUNT(resolverId) into one table. Like:
creatorId,COUNT(creatorId),resolverId,COUNT(resolverId)
'1','2','1','1'
'2','2','2','3'
I only passed the test of putting them in 2 columns by using UNION, and I tried JOIN but it is illegal to MySQL.
SELECT creatorId, COUNT(creatorId)
FROM issue AS a
GROUP BY creatorId
join(
SELECT resolverId, COUNT(resolverId)
FROM issue AS b
GROUP BY resolverId)
WHERE a.creatorId = b.resolverId;
The error info is:
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'join( SELECT resolverId, COUNT(resolverId) FROM issue AS b GROUP BY resolverId)' at line 4 0.00034 sec
Can anyone tell me how to deal with it? or give me a example?
Thank you!
select a.creatorId,COUNT(a.creatorId), t.resolverId, count_resolved_id
from issue a
inner join (
SELECT b.resolverId, COUNT(b.resolverId) count_resolved_id
FROM issue AS b
GROUP BY resolverId
) t on t.resolverId = a.creatorId
group by a.creatorId;
you could jon this way
select a.creatorId,COUNT(acreatorId), resolverId, count_resolved_id
from issue a
inner join (
SELECT resolverId, COUNT(resolverId) count_resolved_id
FROM issue AS b
GROUP BY resolverId
) t on t.resolverId = a.creatorId
group by a.creatorId,COUNT(acreatorId)
If I understand correctly, then one way of doing this is an aggregation after a union all:
select id, sum(creator) as creator_cnt, sum(resolver) as resolver_cnt
from ((select creator_id as id, 1 as creator, 0 as resolver
from issue
) union all
(select resolver_id as id, 0 as creator, 1 as resolver
from issue
)
) cr
group by id;

error in grouping by year,month in mysql

I have this code, and it is working properly on the online server:
SELECT
DATE(`order`.`date`) AS `dater`,
COUNT(*) AS `orders-amount`,
SUM(`order`.`price`) AS `orders-income`,
(SELECT SUM(`amount`) FROM `paypal` WHERE `paypal`.`txn_id` != 'Bonus' AND YEAR(`dater`) = YEAR(`paypal`.`posted_date`) AND MONTH(`dater`) = MONTH(`paypal`.`posted_date`)) AS `total_charge`
FROM `order`
GROUP BY YEAR(`dater`), MONTH(`dater`)
ORDER BY `dater` DESC
But on localhost it gives an error as below:
#1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'panel.order.date' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Id I used this code for grouping then it working properly:
GROUP BY `dater`
This error appear only on localhost as I'm running on linux Mint and installing the apache, php, mysql & pypmyadmin
It means that different sql modes are used on local and remote servers.
Either you should change the mode or update your query like:
SELECT
YEAR(ANY_VALUE(`order`.`date`)) date_year,
MONTH(ANY_VALUE(`order`.`date`)) date_month,
COUNT(*) AS `orders-amount`,
SUM(`order`.`price`) AS `orders-income`,
(SELECT SUM(`amount`) FROM `paypal` WHERE `paypal`.`txn_id` != 'Bonus' AND YEAR(ANY_VALUE(`order`.`date`)) = YEAR(`paypal`.`posted_date`) AND MONTH(ANY_VALUE(`order`.`date`)) = MONTH(`paypal`.`posted_date`)) AS `total_charge`
FROM `order`
GROUP BY date_year, date_month
You have it in your error message:
this is incompatible with sql_mode=only_full_group_by
If you did not set it on purpose, I guess you got it by default and you have a different version on your local server (see here, it was made default at some point).
So all you need is to disable this mode, either by running SET sql_mode='';, or by following instructions here

Prestashop - List view filter

I insert an other column in the list view of my module inserting the values with getList function, I modified the sql to filter in the renderList function but I can't use the alias in where clause.
How can I fix it?
The error i got is the next:
Uncaught Unknown column 'product_supplier_name' in 'where clause'<br /><br />
SELECT SQL_CALC_FOUND_ROWS a.* , s.name AS product_supplier_name FROM ps_supplier_bill a LEFT JOIN ps_supplier s ON s.id_supplier = a.id_product_supplier WHERE 1 AND product_supplier_name LIKE '%fa%' ORDER BY product_supplier_name asc LIMIT 0,50
The proper query should be this:
SELECT SQL_CALC_FOUND_ROWS a.* , s.`name` AS product_supplier_name FROM `ps_supplier_bill` a LEFT JOIN `ps_supplier` s ON s.`id_supplier` = a.`id_product_supplier` WHERE 1 AND s.`name` LIKE '%fa%' ORDER BY s.`name` asc LIMIT 0,50
It's not possible use directly an alias in WHERE, because chronologically, WHERE happens before SELECT, which always is the last step in the execution chain. REFER
From MySQL doc:
Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.
MySQL doc

How to use SELECT DISTINCT ON with MySQL and Rails

I have quite a complex query to essentially select the cheapest delivery service price per delivery service.
In order to get unique records per delivery service, I utilise the DISTINCT function in SQL. This query provides correct results:
DeliveryServicePrice.active.select('DISTINCT ON (delivery_service_id) *').order('delivery_service_id, price ASC')
(only a part of the query)
However, this query only seems to work with PostgreSQL (which I think is strange considering PostgreSQL is a lot more strict with SQL standards); it does not work with MySQL and SQLite. I receive the following error:
Mysql2::Error: You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near 'ON (delivery_service_id) * FROM `delivery_service_prices`
WHERE `delivery_servi' at line 1: SELECT DISTINCT ON
(delivery_service_id) * FROM `delivery_service_prices` WHERE
`delivery_service_prices`.`active` = 1 AND (2808.0 >= min_weight AND
2808.0 <= max_weight AND 104.0 >= min_length AND 104.0 <= max_length AND 104.0 >= min_thickness AND 104.0 <= max_thickness) ORDER BY delivery_service_id, price ASC
The application I'm building is open source, so it's required to support all 3 database types.
How do I create DISTINCT ON queries for MySQL and SQLite in the Rails framework syntax?
I'm using Rails 4.1.
Resources
My previous problem for reference:
How to select unique records based on foreign key column in Rails?
File and line number for where the query is being used.
Finished answer
DeliveryServicePrice.select('delivery_service_prices.id').active.joins('LEFT OUTER JOIN delivery_service_prices t2 ON (delivery_service_prices.delivery_service_id = t2.delivery_service_id AND delivery_service_prices.price > t2.price)').where('t2.delivery_service_id IS NULL')
DISTINCT ON is a Postgres specific extension to the standard SQL DISTINCT. Neither of them is a "function", both are SQL key words - even though the parentheses required after DISTINCT ON make it look like a function.
There are a couple of techniques to rewrite this with standard-SQL, all of them more verbose, though. Since MySQL does not support window-functions row_number() is out.
Details and more possible query techniques:
Select first row in each GROUP BY group?
Fetch the row which has the Max value for a column
Rewritten with NOT EXISTS:
SELECT *
FROM delivery_service_prices d1
WHERE active = 1
AND 2808.0 BETWEEN min_weight AND max_weight
AND 104.0 BETWEEN min_length AND max_length
AND 104.0 BETWEEN min_thickness AND max_thickness
AND NOT EXISTS (
SELECT 1
FROM delivery_service_prices d2
WHERE active = 1
AND 2808.0 BETWEEN min_weight AND max_weight
AND 104.0 BETWEEN min_length AND max_length
AND 104.0 BETWEEN min_thickness AND max_thickness
AND d2.delivery_service_id = d1.delivery_service_id
AND d2.price < d1.price
AND d2.<some_unique_id> < d1.<some_unique_id> -- tiebreaker!
)
ORDER BY delivery_service_id
If there can be multiple rows with the same price for the same delivery_service_id, you need to add some unique tie-breaker to avoid multiple results per delivery_service_id. At least if you want a perfectly equivalent query. My example would select the row with the smallest <some_unique_id> from each set of dupes.
Unlike with DISTINCT ON, ORDER BY is optional here.
DeliveryServicePrice.active.select(:delivery_service_id).distinct.order('delivery_service_id, price ASC')