I have the following query which takes more than 20 secs (20138ms) to return the results.
$locale = 'en'; // test
$query = $this->getEntityManager()->createQuery('
SELECT
product.id, product.productnr, ProductGrp.productgrp' . $locale . ', Criteria.criteria'.$locale.'
FROM
Productbundle:product product
JOIN
Productbundle:Criteria Criteria WITH Criteria.criteriaid = product.criteriaid
JOIN
Productbundle:ProductGrp ProductGrp WITH ProductGrp.partgrpid = product.partgrpid
WHERE
product.productnr =:productnr
')
->setMaxResults(1)
->setParameter('productnr', $productnr)
->getResult();
when I ran the query from "runnable query" it took about 20 secs (20.7809) in phpmyadmin.
runnable query :
SELECT o0_.id AS id0, o0_.productnr AS productnr1, o1_.productgrpen AS productgrpen2, o2_.criteriaen AS criteriaen3
FROM product o0_
INNER JOIN Criteria o2_ ON (o2_.criteriaid = o0_.criteriaid)
INNER JOIN ProductGrp o1_ ON (o1_.partgrpid = o0_.partgrpid)
WHERE o0_.productnr = 'ABC1234'
LIMIT 1;
However when I ran the following code in phpmyadmin it takes less than 2seconds to return the results
SELECT product.id, product.productnr,ProductGrp.productgrpen ,Criteria.criteriaen
FROM `product`
INNER JOIN ProductGrp ON ProductGrp.partgrpid = product.partgrpid
INNER JOIN Criteria ON Criteria.criteriaid = product.criteriaid
Where productnr = 'ABC1234'
LIMIT 1
table size
-------------------------------
|Product | over 5mill rows |
-------------------------------
|ProductGrp | over 200 rows |
-------------------------------
|Criteria | over 600 rows |
-------------------------------
Symfony version : 2.7
Indexes although not listed, I would suggest the following
table indexed on
Product (productnr, id, criteriaid, partgrpid )
Criteria (criteriaid ) -- would expect as primary key
ProductGrp (partgrpid ) -- also would expect
Also, how many "locale" string version columns do you have / support.
Related
We have a scenario where users answer some questions related to a parent entity that we'll call a widget. Each question has both a numeric and word answer. Multiple users answer each question for a given widget.
We then display a row for each widget with the average numeric answer for each question. We do that using a MySQL pseudo-pivot with dynamic columns as detailed here So we end up with something like:
SELECT widget_id, ...
ROUND(IFNULL(AVG(CASE
WHEN LOWER(REPLACE(RQ.question, ' ', '_')) = 'overall_size' THEN
if(RA.num = '', 0, RA.num) END),0) + .0001, 2) AS `raw_avg_overall_size`,
...
... where overall_size would be one of the question types related to the widget and might have "answers" from 5 users like 1,2,2,3,1 to that question for a given widget_id based on the answer options below:
Answers
answer_id
answer_type
num
word
111
overall_size
1
x-large
112
overall_size
2
large
113
overall_size
3
medium
114
overall_size
4
small
115
overall_size
5
x-small
So we would end up with a row that had something like this:
widget_id
average_overall_size
115
1.80
What we can't figure out is then given if we round 1.80 to zero precision we get 2 in this example which is the word value 'large' from our data above. We like to include that in the query output too so that end up with:
widget_id
raw_average_overall_size
average_overall_size
115
1.80
large
The issue is that we do not know the average for the row until the query runs. So how can we then reference the word value for that average answer in the same row when executing the query?
As mentioned we are pivoting into a variable and then run another query for the full execution. So if we join in the pivot section, that subquery looks something like this:
SET #phase_id = 1;
SET SESSION group_concat_max_len = 100000;
SET #SQL = NULL;
SET #NSQL = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT(
'ROUND(IFNULL(AVG(CASE
WHEN LOWER(REPLACE(RQ.short_question, '' '', ''_'')) = ''',
nsq,
''' THEN
if(RA.answer = '''', 0, RA.answer) END),0) + .0001, 2) AS `',
CONCAT('avg_raw_',nsq), '`,
REF.value, -- <- ******* THIS FAILS **** --
ROUND(IFNULL(STDDEV(CASE
WHEN LOWER(REPLACE(RQ.short_question, '' '', ''_'')) = ''',
nsq,
''' THEN RA.answer END), 0) + .0001, 3) AS `',
CONCAT('std_dev_', nsq), '`
'
)
ORDER BY display_order
) INTO #NSQL
FROM (
SELECT FD.ref_value, FD.element_name, RQ.display_order, LOWER(REPLACE(RQ.short_question, ' ', '_')) as nsq
FROM review_questions RQ
LEFT JOIN form_data FD ON FD.id = RQ.form_data_id
LEFT JOIN ref_values RV on FD.ref_value = RV.type
WHERE RQ.phase_id = #phase_id
AND FD.element_type = 'select'
AND RQ.is_active > 0
GROUP BY FD.element_name
HAVING MAX(RV.key_name) REGEXP '^[0-9]+$'
) nq
/****** suggested in 1st answer ******/
LEFT JOIN ref_values REF ON REF.`type` = nq.ref_value
AND REF.key_name = ROUND(CONCAT('avg_raw_',nsq), 0);
So we need the word answer (from the REF join's REF.value field in the above code) in the pivot output, but it fails with 'Unknown column REF.value. If we put REF.value in it's parent query field list, that also fails with the same error.
You'll need to join the table/view/query again to get the 'large' value.
For example:
select a.*, b.word
from (
-- your query here
) a
join my_table b on b.answer_id = a.answer_id
and b.num = round(a.num);
An index on my_table (answer_id, num) will speed up the extra search.
This fails, leading to the default of "2":
LOWER(REPLACE(RQ.question, ' ', '_')) = 'overall_size'
That is because the question seems to be "average_overall_size", not "overall_size".
String parsing and manipulation is the pits in SQL; suggest using the application to handle such.
Also, be aware that you may need a separate subquery to compute aggregate (eg AVG()), else it might not be computed over the set of values you think.
Query into temp table, then join
First query should produce table as follows:
CREATE temp table, temp_average_size
widget_id
average_overall_size
rounded_average_size
115
1.80
2
LEFT JOIN
select s.*, a.word
from temp_average_size s LEFT JOIN answers a
ON (s.rounded_average_size = a.num AND a.answer_type = 'overall_size)
I want to select a date range with specific provider ID and this query should print 2 data only since there's only 2 row with provider id = 1
SQL Query:
SELECT logs_tb.logs_id
,logs_tb.time_in
,logs_tb.status
,logs_tb.provider_id
,users_tb.user_first_name
,users_tb.user_last_name
,users_tb.user_contactno
,users_tb.user_city
,users_tb.user_avatar
,users_tb.user_email
,users_tb.user_contactno
,users_tb.user_uuid
FROM logs_tb
,users_tb
WHERE logs_tb.provider_id = 1
AND logs_tb.log_date BETWEEN '2022-03-25' AND '2022-03-26'
ORDER BY logs_tb.logs_id desc;
Table:
Output:
I used ON condition, thank you M.Hermant
Query:
SELECT logs_tb.logs_id, logs_tb.time_in, logs_tb.status, logs_tb.provider_id, users_tb.user_first_name, users_tb.user_last_name, users_tb.user_contactno, users_tb.user_city, users_tb.user_avatar, users_tb.user_email, users_tb.user_contactno, users_tb.user_uuid
FROM users_tb
INNER JOIN logs_tb
ON users_tb.user_id = logs_tb.user_id
WHERE (logs_tb.log_date BETWEEN '2022-03-25' AND '2022-03-26') AND logs_tb.provider_id = 1
ORDER BY logs_tb.log_date desc;
Output:
i have 3 table with structures
plans
- id
- cost_center_code
- cost_element_code
- val_usd
commitments
- id
- cost_center_code
- cost_element_code
- val_usd
actuals
- id
- cost_center_code
- cost_element_code
- val_usd
i want join 3 table using 2 key (cost_center_code,cost_element_code) and show sum val_usd from each table
this my current query and took 15-20s
select
plans.cost_center_code,
plans.cost_element_code,
sum(plans.val_usd) as plan_usd,
sum(commitments.val_usd) as commitment_usd,
sum(actuals.val_usd) as actual_usd
from `plans`
left join `commitments`
on
`plans`.`cost_center_code` = `commitments`.`cost_center_code`
and `plans`.`cost_element_code` = `commitments`.`cost_element_code`
left join `actuals`
on
`plans`.`cost_center_code` = `actuals`.`cost_center_code`
and `plans`.`cost_element_code` = `actuals`.`cost_element_code`
where
date(`plans`.`document_date`) = '2021-07-27'
and date(`commitments`.`document_date`) = '2021-07-27'
and date(`actuals`.`document_date`) = '2021-07-27'
and `plans`.`deleted_at` is null
group by `plans`.`cost_center_code`, `plans`.`cost_element_code`
limit 10
[edit]
my query result
EXPLAIN query result
I have many tables with the same structure for each of my costumers.
All information are distinct for each table.
For some reason, I need to create some temporary table with the same structure with 200 values everytime I run.
So let's assume I have 3 tables.
Costumer1, Costumer2, Costumer3.
All those tables have id, user_name, contact_name, contact_email, sent1, sent2, sent3, sent4, status.
I need some query to put inside costumer_tmp, only 200 values in total, from all those 3 tables, everytime I run the script. And everytime I run cant repeat the last values I got before.
So for example:
Costumer1
id = 29
user_name = test1
contact_name = contact1
contact_email = contact1#mail.com
sent1 = yes
sent2 = no
sent3 = no
sent4 = no
status = In Progress
Costumer2
id = 37
user_name = test2
contact_name = contact123
contact_email = contact123#mail.com
sent1 = yes
sent2 = no
sent3 = no
sent4 = no
status = In Progress
Costumer3
id = 87
user_name = test3
contact_name = contact231
contact_email = contact231#mail.com
sent1 = yes
sent2 = no
sent3 = no
sent4 = no
status = In Progress
How to Insert on costumer_tmp only 2 records of those 3 and next time I run the script don't repeat those 2 records, just insert only 1 record remaining.
Your requirement is a bit weird, but if I understand weel, how about something like : (not tested)
insert into costumer_tmp
select * from Costumer1 one where one.id not in (select id from costumer_tmp)
union all
select * from Costumer2 two where two.id not in (select id from costumer_tmp)
union all
select * from Costumer3 three where three.id not in (select id from costumer_tmp) LIMIT 200
I use MySQL 5.7 and have the following tables:
documents:
---------------------------------------------------------------
id collection_id numeric_shelfmark shelfmark
---------------------------------------------------------------
1 kbt y024 Y 24
---------------------------------------------------------------
collections:
---------------------------------------------------------------
id name location
---------------------------------------------------------------
kbt kantonb thur Thurgau
gbt lorem ipsum
----------------------------------------------------------------
subprojects_x_documents
-----------------------------------------------------------------
subproject_id document_id
-----------------------------------------------------------------
foo 1
-----------------------------------------------------------------
documents_revisions
-----------------------------------------------------------------
document_id updated_at numeric_shelfmark shelfmark latest
-----------------------------------------------------------------
1 2016-06-22 10:32:01 y024 Y 24 0
1 2017-09-19 09:19:17 z024 Z 24 1
------------------------------------------------------------------
With the following SELECT query I could manage to get a list of the documents associated with the subproject and collections:
SELECT `documents`.`id`, `documents`.`collection_id`,
`documents`.`numeric_shelfmark`, `shelfmark`, `location`, `name`
FROM (`documents`)
JOIN `collections` ON `documents`.`collection_id` = `collections`.`id`
JOIN `subprojects_x_documents` ON `documents`.`id` =
`subprojects_x_documents`.`document_id`WHERE
`subprojects_x_documents`.`subproject_id` = 'stgall_lotterie'
ORDER BY `location`, `name`, `documents`.`sort_order`, `numeric_shelfmark`
Now, I'm trying to get the latest ("documents_revisions.latest" = 1) revision of document with:
SELECT `documents`.`id`, `documents`.`collection_id`,
`documents`.`numeric_shelfmark`, `documents`.`shelfmark`, `location`,
name`FROM (`documents`)JOIN `collections` ON
`documents`.`collection_id` = `collections`.`id`JOIN
`documents_revisions` ON `documents_revisions`.`document_id` =
`documents`.`id`JOIN `subprojects_x_documents` ON `documents`.`id` =
`subprojects_x_documents`.`document_id` WHERE
`subprojects_x_documents`.`subproject_id` = 'stgall_lotterie' AND
`documents_revisions`.`latest` = 1 ORDER BY `location`, `name`,
`documents`.`sort_order`, `numeric_shelfmark`
But this query returns the same list of documents as before and ignores the documents_revisions.latest" = 1 part.
When I update the query to perform the operation on documents_revisons table instead of documents table:
SELECT `documents`.`id`, `documents`.`collection_id`,
documents.numeric_shelfmark, documents.shelfmark, location,
nameFROM (documents_revisions)JOIN collections ON
documents.collection_id = collections.idJOIN
documents_revisions ON documents_revisions.document_id =
documents.idJOIN subprojects_x_documents ON documents.id =
subprojects_x_documents.document_id WHERE
subprojects_x_documents.subproject_id = 'stgall_lotterie' AND
documents_revisions.latest = 1 ORDER BY location, name,
documents.sort_order, numeric_shelfmark
I get the error message: "Not unique table/alias: 'documents_revisions'"
Your table is called documents, not document
Ok, after some tweaking I got my result with:
SELECT documents_revisions.document_id,
documents_revisions.collection_id,
documents_revisions.numeric_shelfmark,
documents_revisions.shelfmark, location, nameFROM
(documents_revisions)JOIN collections ON
documents_revisions.collection_id = collections.id JOIN
subprojects_x_documents ON documents_revisions.document_id =
subprojects_x_documents.document_id WHERE
subprojects_x_documents.subproject_id = 'stgall_lotterie' AND
documents_revisions.latest = 1 ORDER BY location, name,
numeric_shelfmark