Missing row from MariaDB result set when constants used twice - once inside derived table and once outside - mariadb

Why is only 1 row returned when 2 definitely exist?
Here is the query I am trying to run:
select t.term_id, t.name, t.slug, a.c, a.term_order, a.menu_order, ttparent.taxonomy from
(
SELECT p.term_id, count(distinct p.ID) c, p.term_order, p.menu_order
FROM pz_fww_object_ancestors p
WHERE p.taxonomy = 'product_cat' and p.term_id IN (1445,9561) group by term_id
) a inner join pz_terms t
ON a.term_id = t.term_id inner join pz_term_taxonomy ttparent on ttparent.term_id = t.term_id
and t.term_id IN (1445, 9561)
;
There should be 2 rows returned, but only 1 row is returned - the one for 1445.
However - this row DEFINITELY should be returnable. If I change the final line of the query to term_id in (9561) then it does return the other row.
One workaround I can do is to remove this extra check of these constants against the term_id, but I'm aware that the MySQL optimizer will not infer or pass through constants from derived tables and so there could be potential in some cases for the optimizer to run this query slowly if I don't also have these constants at the top level of the query rather than just on the derived table.
Here's the 2 result set with the constants removed from the outer/top-level query:
I've looked at the EXPLAIN and yes, the queries run in a different order when this additional constant check exists at the top level, so I presume this is where the bug exists.
Here's the explain from the working query, without the constants added to the top level query:
In case it matters, this is all with MariaDB version 10.3.31-MariaDB-0ubuntu0.20.04.1.

Related

Sqlite Update with Select subquery only chosing first value

I'm having a difficult time getting the UPDATE command in Sqlite to update all records with a new value it finds in another table using a subquery select statement. It incorrectly updates every column in Table1 with the first value it finds in column Table2.
When I run the select portion of the query alone it runs fine and returns all the proper values. It basically looks up the nearest value in multiples of 300000 from a lookup table called Adjustment.
code:
Update TEMP1
set New_position =
(
select (Temp1.Col1 + Adjustment.Offset) as NewValue
from Adjustment, TEMP1
where Adjustment.LookupValue = cast(TEMP1.Col1 / 300000 as Int) * 300000
)
You are trying to use a correlated subquery:
A SELECT statement used as either a scalar subquery or as the right-hand operand of an IN, NOT IN or EXISTS expression may contain references to columns in the outer query. Such a subquery is known as a correlated subquery. A correlated subquery is reevaluated each time its result is required. An uncorrelated subquery is evaluated only once and the result reused as necessary.
But your subquery does not actually contain a reference to columns in the outer query; the FROM Temp1 in the inner query is a new instance of the Temp1 table, and Temp1.Col1 refers to that. The value of Temp1.Col1 is from some random row in Temp1.
Just drop the Temp1 from the FROM clause:
UPDATE Temp1
SET New_position = (SELECT Temp1.Col1 + Adjustment.Offset
FROM Adjustment
WHERE LookupValue = CAST(Temp1.Col1 / 300000 AS INT) * 300000);

Update row with value from next row sqlite

I have the following columns in a SQLite DB.
id,ts,origin,product,bid,ask,nextts
1,2016-10-18 20:20:54.733,SourceA,Dow,1.09812,1.0982,
2,2016-10-18 20:20:55.093,SourceB,Oil,7010.5,7011.5,
3,2016-10-18 20:20:55.149,SourceA,Dow,18159.0,18161.0,
How can I populate the 'next timestamp' column (nextts) with the next timestamp for the same product (ts), from the same source? I've been trying the following, but I can't seem to put a subquery in an UPDATE statement.
UPDATE TEST a SET nextts = (select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1);
If I call this, I can display it, but I haven't found a way of updating the value yet.
select a.*,
(select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1) as nextts
from TEST a
order by origin, a.id;
The problem is that you're using table alias for table in UPDATE statement, which is not allowed. You can skip alias from there and use unaliased (but table-name prefixed) reference to its columns (while keeping aliased references for the SELECT), like this:
UPDATE TEST
SET nextts = (
SELECT b.ts
FROM TEST b
WHERE b.id > TEST.id AND
TEST.origin = b.origin AND
TEST.product = b.product
ORDER BY b.id ASC
LIMIT 1
);
Prefixing unaliased column references with the table name is necessary for SQLite to identify that you're referencing to unaliased table. Otherwise the id column whould be understood as the id from the closest[*] possible data source, in which case it's the aliased table (as b alias), while we're interested in the unaliased table, therefore we need to explicitly tell SQLite that.
[*] Closest data source is the one listed in the same query, or parent query, or parent's parent query, etc. SQLite is looking for the first data source (going from inner part to the outside) in the query hierarchy that defines this column.

How to improve sqlite SELECT performance?

Some SELECT statements take several seconds to return data and I would like to know if and how I could improve performance. The DB normally is quite small (~10-40MB) but the larger it gets, the longer it takes.
One example query which takes very long is the following:
SELECT intf_id FROM interfaces
WHERE intfType IN (SELECT intfType FROM interfaces
WHERE intf_id=39151)
AND macAddress IN (SELECT l2_addr FROM neighbor
INNER JOIN nlink ON nlink.neighbor_neighbor_id=neighbor.neighbor_id
INNER JOIN interfaces ON interfaces.intf_id=nlink.interfaces_intf_id
WHERE interfaces.intf_id=39151)
AND status LIKE 'UP' AND phl=1 AND intf_id <> 39151
Maybe it's because of the nested SELECT statements?
The DB Layout is as follows:
EXPLAIN QUERY PLAN Output:
EXPLAIN QUERY PLAN csv:
"0","0","0","SCAN TABLE interfaces USING COVERING INDEX ii1"
"0","0","0","EXECUTE LIST SUBQUERY 1"
"1","0","0","SEARCH TABLE interfaces USING INTEGER PRIMARY KEY (rowid=?)"
"0","0","0","EXECUTE LIST SUBQUERY 2"
"2","0","2","SEARCH TABLE interfaces USING INTEGER PRIMARY KEY (rowid=?)"
"2","1","0","SCAN TABLE neighbor"
"2","2","1","SEARCH TABLE nlink USING COVERING INDEX sqlite_autoindex_nlink_1 (neighbor_neighbor_id=? AND interfaces_intf_id=?)"
could you try creating an index on interfaces.macAddress and using the following joined Query instead? The subqueries seem to be slower in this case.
SELECT interface_RH.intf_id FROM interfaces AS interface_LH
INNER JOIN nlink ON nlink.interfaces_intf_id = interface_LH.intf_id
INNER JOIN neighbor ON nlink.neighbor_neighbor_id = neighbor.neighbor_id
INNER JOIN interfaces AS interface_RH ON interface_RH.macAddress = neighbor.l2_addr
WHERE
interface_LH.intf_id=39151
AND interface_RH.status LIKE 'UP'
AND interface_RH.phl = 1
AND interface_RH.intf_id <> 39151
AND interface_RH.intfType = interface_LH.intfType

selecting only max clause without group by properties in subquery using Nhibernate

I have SQL query like this:
select * from dbo.table1 where Id in
(
select max(id) as id from dbo.table1 group by prop1, prop2, prop3
)
I want to create NHibernate query which is be able to do this for me. I tried to use QueryOver but it doesn't work. Do you have any suggestions how to do it?
NHibernate supports even this kind of queries. Please, see more in documentation: 15.8. Detached queries and subqueries. We just have to split the query (as in your SQL snippet) into two parts:
inner select
the select with the IN clause
Let's assume, that the dbo.table1 in the Questin is mapped into MyEntity.
To create inner select, let's use the DetachedCriteria
EDIT (extended with the Group by, SqlGroupProjection)
There is an extract of the SqlGroupProjection method:
A grouping SQL projection, specifying both select clause and group by
clause fragments
// inner select
DetachedCriteria innerSelect = DetachedCriteria
.For(typeof(MyEntity))
.SetProjection(
Projections.ProjectionList()
.Add(
Projections.SqlGroupProjection(
" MAX(ID) ", // SELECT ... max(ID) only
" Prop1, Prop2, Prop3", // GROUP BY ... property1, p2...
new string[] {"ID"}, // could be empty, while not used for
new IType[] { NHibernate.NHibernateUtil.Int32 } // transformation
)
)
;
Note: I've provided even the last two paramters, but in this case they could be empty: new string[], new IType[] {}. These are used only for Transformation (materialization from data into entity). And this is not the case, we are just building inner select...
// the select with IN clause
var result = session.CreateCriteria(typeof(MyEntity))
.Add(Subqueries.PropertyIn("ID", innerSelect))
.List<MyEntity>();
Also related could be 15.7. Projections, aggregation and grouping

Symfony2, Doctrine DQL, Subquery, get values from another table using a condition

As far as I know, doctrine dql does not allow subqueries inside a join.
I have a table and a trasnlation table. The relation is one to many. One record has many translations.
In order to get the right translation row from the translatiosn table I did subselects in the select clause:
$query = $this->getDoctrine()->getEntityManager()
->createQuery('
SELECT w.id, w.pastid, w.name, w.jsonParameters as params, m.id as milestone_id, m.name as milestone_name,
m.slug as milestone_slug, m.startdate as milestone_start, m.enddate as milestone_end,
w.expand as expand, w.backgroundcolor as background, w.colorschema as colorschema, w.headline as headline, w.subheadline as subheadline, w.text as text, w.expandheight as expandheight,
w.url as url, w.created as created, w.updated as updated, wt.name as wtname, ws.weight as width, ws.height as height
, (SELECT t.headline FROM AdminBundle:widgetTranslation t WHERE t.widget = w.id and t.locale = :published) AS headline_trans
, (SELECT t2.subheadline FROM AdminBundle:widgetTranslation t2 WHERE t2.widget = w.id and t2.locale = :published) AS subheadline_trans
, (SELECT t3.text FROM AdminBundle:widgetTranslation t3 WHERE t3.widget = w.id and t3.locale = :published) AS text_trans
FROM AdminBundle:Widget w
JOIN w.milestone m
JOIN w.widgetType wt
JOIN w.widgetShape ws
WHERE w.published = 1
ORDER BY m.order, w.order
')->setParameter('published', $currentLocale);
$result = $query->getArrayResult();
This query does the job but Iam worried about performance, is there a better query to do this?
First, I need to clarify a little thing.
There is something really wrong in your question.
You are using an ORM, right? But you're talking about tables.
An ORM doesn't care about how your tables are organized or linked together. It only matters on the relationship between the objects themselves.
However, if you are worried about performance, the best thing to do, as you would do it with any SQL query, is to EXPLAIN it.
Since you're using Symfony 2.0, you may use the profiler (accessible in dev env) to see the EXPLAIN results of your query.
Make sure that is using index, and the number of rows to lookup is not too high.
Depending on your result you may need to use another strategy to fetch your translation or re-write your query in native SQL to allow more flexibility.

Resources