MySQL: query'ing results [pic] - mysql

I almost have the data I want...but need help filtering it. (pic at bottom)
The query below returns all records with a status of Member-id5 but I need to filter that. Ex: If I did a simple query on ect. (exp_channel_titles) for author_id 323 I would get 5 results. Of those 5 results one row has status = 'Member-id5', another one has a status = 'complete' AND title = %Member% (that's the deciding factor, the row with complete and Member in it). If that row exist then its okay to grab the entry_id of row status = Member-id5 to use for looking up the data in ecd (exp_channel_data) with in it. Any idea on how i can do that? picture enclosed
SELECT
ect.entry_id
, ect.author_id
, ect.title
, ect.status
, ecd.field_id_13
, ecd.field_id_14
, ecd.field_id_15
, ecd.field_id_25
, ecd.field_id_27
, ecd.field_id_28
, ecd.field_id_29
, ecd.field_id_30
, ecd.field_id_31
, ecd.field_id_32
, ecd.field_id_33
, ecd.field_id_34
, ecd.field_id_35
, exm.email
FROM exp_channel_titles as ect
LEFT JOIN exp_channel_data as ecd
ON ecd.entry_id = ect.entry_id
LEFT JOIN exp_members as exm
ON exm.member_id = ect.author_id
WHERE ect.status = 'Members-id5'
The picture is just of a simple query done on exp_channel_titles, of 323 as author_id. its to show how there multiple results and what entry_id i'm trying to get in order to finish my query. entry_id 496 is what I want, and that based on 1. there is a row with %Member% and complete in it. And then row 496 has a status of Members-id5.

SELECT ...
FROM exp_channel_titles as ect
JOIN exp_channel_titles as ect2
ON (
ect2.author_id = ect.author_id
AND ect2.title LIKE '%Member%'
AND ect2.status = 'complete'
)
...
WHERE ect.status = 'Members-id5'

Related

Remove Duplicate rows in left join base on one column

I want to remove the duplicates column with the same id. I want to keep only the first one that shows up.
SELECT t.ticketId ,t.userIdOwner , t.ticketCreateDatetime , t.ticketExpectedEndDatetime , t.ticketUpdateDatetime, t.ticketUpdateBy, t.ticketLabel,t.statusTypeIdTicketState,t.statusTypeIdTicketType,t.statusTypeIdTicketModule,
c.clientLabel, c.clientLogoOnList ,s.taskLabel , s.statusTypeIdTaskCompletion
FROM ticket AS t
INNER JOIN client AS c
ON c.clientId = t.clientId
LEFT JOIN task AS s
ON s.ticketId = t.ticketId AND s.statusTypeIdTaskCompletion = (SELECT statusTypeId FROM statusType WHERE statusTypeCode = 'waitingTask' AND statusTypeTargetTable = 'statusTypeIdTaskCompletion' )
WHERE 1=1
AND t.ticketDeleteDatetime IS NULL
Here's my screen of results
Edit Image query all results
enter image description here
Edit Image of task structure table :
enter image description here
You probably have more tasks for each ticket with same statusType
so, if you don't care about different tasks, you can simply add a DISTINCT clause in your SELECT
SELECT DISTINCT
t.ticketId ,t.userIdOwner , t.ticketCreateDatetime , t.ticketExpectedEndDatetime ,
t.ticketUpdateDatetime, t.ticketUpdateBy, t.ticketLabel,t.statusTypeIdTicketState,
t.statusTypeIdTicketType,t.statusTypeIdTicketModule,
c.clientLabel, c.clientLogoOnList ,s.taskLabel , s.statusTypeIdTaskCompletion
FROM ticket AS t
INNER JOIN client AS c ON c.clientId = t.clientId
LEFT JOIN task AS s ON s.ticketId = t.ticketId AND s.statusTypeIdTaskCompletion = (
SELECT statusTypeId
FROM statusType
WHERE statusTypeCode = 'waitingTask'
AND statusTypeTargetTable = 'statusTypeIdTaskCompletion'
)
WHERE 1=1
AND t.ticketDeleteDatetime IS NULL
ok, after your edit, now we can see, that the problem is that more than one task is eligible for the ticket.
Unfortunaterly "the first that show up" is not a valid SQL statement (because the same query could give different results depending on different circumnstances).
So you have to decide wich one to keep, you need to decide a rule, a logic to keep one of the rows.
If you don't need the task label you can simply strip off that column and use the DISTINCT.
If you want to show a task label but don't mind which one, you can use MAX(s.taskLabel) and group by on all other columns.
If you want to keep the last task for that ticket you should provide informations about cronological order (a datetime column or an autoincrement column)
Example with MAX(taskLabel):
SELECT
t.ticketId,
t.userIdOwner,
t.ticketCreateDatetime,
t.ticketExpectedEndDatetime,
t.ticketUpdateDatetime,
t.ticketUpdateBy,
t.ticketLabel,
t.statusTypeIdTicketState,
t.statusTypeIdTicketType,
t.statusTypeIdTicketModule,
c.clientLabel,
c.clientLogoOnList,
s.taskLabel,
s.statusTypeIdTaskCompletion
FROM ticket AS t
INNER JOIN client AS c ON c.clientId = t.clientId
LEFT JOIN (
SELECT s.ticketId, MAX(s.taskLabel) AS taskLabel
FROM task AS s
WHERE s.statusTypeIdTaskCompletion = (
SELECT statusTypeId
FROM statusType
WHERE statusTypeCode = 'waitingTask'
AND statusTypeTargetTable = 'statusTypeIdTaskCompletion'
)
GROUP BY s.ticketId
) S ON s.ticketId = t.ticketId
WHERE 1=1
AND t.ticketDeleteDatetime IS NULL

How to make query

review table has store_idx, user_idx etc...
I want to create a query sentence that gets information about the store to which the user has bookmarked with the user_id value entered.
The query sentence I made is
select A.store_name
, A.store_img
, count(B.store_idx) as review_cnt
from board.store A
Left
Join board.review B
On A.store_idx is B.store_idx
where store_idx is (select A.store_idx from bookmark where user_id = ?)
However, nothing came out as a result.
Help me..
Please use below Query:
SELECT store_name
, store_img
, SUM(review_cnt) AS review_cnt
FROM
( SELECT DISTINCT A.store_name
, A.store_img
, CASE WHEN B.store_idx IS NULL THEN 0 ELSE 1 END AS review_cnt
FROM bookmark br
JOIN board.store A
ON A.store_idx = br.store_idx
LEFT
JOIN board.review B
ON A.store_idx = B.store_idx
WHERE br.user_id = ?
)T
The WHERE clause is obviously filtering out all rows. We can't do much about that. But your query is also lacking a GROUP BY, the table aliases can be improved, and the join condition is not correct.
So, try this version:
select s.store_name, s.store_img, count(b.store_idx) as review_cnt
from board.store s left join
board.review r
on s.store_idx = r.store_idx
where b.store_idx in (select b.store_idx
from bookmark b
where b.user_id = ?
);

MySQL Multiple Join Query with Limit on One Join

I have a MYSQL query I'm working on that pulls data from multiple joins.
select students.studentID, students.firstName, students.lastName, userAccounts.userID, userstudentrelationship.userID, userstudentrelationship.studentID, userAccounts.getTexts, reports.pupID, contacts.pfirstName, contacts.plastName, reports.timestamp
from userstudentrelationship
join userAccounts on (userstudentrelationship.userID = userAccounts.userID)
join students on (userstudentrelationship.studentID = students.studentID)
join reports on (students.studentID = reports.studentID)
join contacts on (reports.pupID = contacts.pupID)
where userstudentrelationship.studentID = "10000005" AND userAccounts.getTexts = 1 ORDER BY reports.timestamp DESC LIMIT 1
I have a unique situation where I would like one of the joins (the reports join) to be limited to the latest result only for that table (order by reports.timestamp desc limit 1 is what I use), while not limiting the result quantities for the overall query.
By running the above query I get the data I would expect, but only one record when it should return several.
My question:
How can I modify this query to ensure that I receive all possible records available, while ensuring that only the latest record from the reports join used? I expect that each record will possibly contain different data from the other joins, but all records returned by this query will share the same report record
Provided I understand the issue; one could add a join to a set of data (aliased Z below) that has the max timestamp for each student; thereby limiting to one report record (most recent) for each student.
SELECT students.studentID
, students.firstName
, students.lastName
, userAccounts.userID
, userstudentrelationship.userID
, userstudentrelationship.studentID
, userAccounts.getTexts
, reports.pupID
, contacts.pfirstName
, contacts.plastName
, reports.timestamp
FROM userstudentrelationship
join userAccounts
on userstudentrelationship.userID = userAccounts.userID
join students
on userstudentrelationship.studentID = students.studentID
join reports
on students.studentID = reports.studentID
join contacts
on reports.pupID = contacts.pupID
join (SELECT max(timestamp) mts, studentID
FROM REPORTS
GROUP BY StudentID) Z
on reports.studentID = Z.studentID
and reports.timestamp = Z.mts
WHERE userstudentrelationship.studentID = "10000005"
AND userAccounts.getTexts = 1
ORDER BY reports.timestamp
for get all the records you should avoid limit 1 at the end of the query
for join anly one row from reports table you could use subquery as
select
students.studentID
, students.firstName
, students.lastName
, userAccounts.userID
, userstudentrelationship.userID
, userstudentrelationship.studentID
, userAccounts.getTexts
, t.pupID
, contacts.pfirstName
, contacts.plastName
, t.timestamp
from userstudentrelationship
join userAccounts on userstudentrelationship.userID = userAccounts.userID
join students on userstudentrelationship.studentID = students.studentID
join (
select * from reports
order by reports.timestamp limit 1
) t on students.studentID = t.studentID
join contacts on reports.pupID = contacts.pupID
where userstudentrelationship.studentID = "10000005"
AND userAccounts.getTexts = 1

query taking long time to execute and crashing the site

I am having around 2.5 lachs (250K) products and 2600 subcategories on magento application (community edition).
Query
SELECT 1 status
, e.entity_id
, e.type_id
, e.attribute_set_id
, cat_index.position AS cat_index_position
, e.name
, e.description
, e.short_description
, e.price
, e.special_price
, e.special_from_date
, e.special_to_date
, e.cost
, e.small_image
, e.thumbnail
, e.color
, e.color_value
, e.news_from_date
, e.news_to_date
, e.url_key
, e.required_options
, e.image_label
, e.small_image_label
, e.thumbnail_label
, e.msrp_enabled
, e.msrp_display_actual_price_type
, e.msrp
, e.tax_class_id
, e.price_type
, e.weight_type
, e.price_view
, e.shipment_type
, e.links_purchased_separately
, e.links_exist
, e.open_amount_min
, e.open_amount_max
, e.custom_h1
, e.awards
, e.region
, e.grape_type
, e.food_match
, e.udropship_vendor
, e.upc_barcode
, e.ean_barcode
, e.mpn
, e.size
, e.author
, e.format
, e.pagination
, e.publish_date
, price_index.price
, price_index.tax_class_id
, price_index.final_price
, IF(price_index.tier_price IS NOT NULL
, LEAST(price_index.min_price
, price_index.tier_price)
, price_index.min_price) AS minimal_price
, price_index.min_price
, price_index.max_price
, price_index.tier_price
FROM catalog_product_flat_1 e
JOIN catalog_category_product_index cat_index
ON cat_index.product_id = e.entity_id
AND cat_index.store_id = 1
AND cat_index.visibility IN(2,4)
AND cat_index.category_id = 163
JOIN catalog_product_index_price price_index
ON price_index.entity_id = e.entity_id
AND price_index.website_id = 1
AND price_index.customer_group_id = 0
GROUP
BY e.entity_id
ORDER
BY cat_index_position ASC
, cat_index.position ASC
LIMIT 15;
whenever accessing any products on this magento site it created a huge data under /tmp directory on theserver which is around 10 GB.
How can I fix this please suggest some solution.
Database size is 50 GB and server is nginx.
You are misusing GROUP BY. Please learn how it works. There's a misfeature in MySQL which allows you to misuse it. Unfortunately, queries that misuse it are very difficult to troubleshoot.
It is difficult to infer what you are trying to do from your query. When you're dealing with result sets of that size, it helps to know your intent.
You should know, if you don't already, that queries of the form
SELECT <<many columns>>
FROM large_table
JOIN another_large_table ON something
JOIN another_large_table ON something
ORDER BY some_arbitrary_column
LIMIT some_small_number
can be grossly inefficient because they have to generate an enormous result set, then sort the whole thing, then return the first results. The sort operation carries the whole result set with it. You could be instructing the MySQL server to sort a crore or two of rows (dozens of megarows).
It looks like you want the first fifteen results starting with the lowest cat_index.position value. Accordingly, you may be able to make your query faster by joining with an appropriate subset of the table you call cat_index, like so:
SELECT 1 status, many_other_columns
FROM catalog_product_flat_1 e
JOIN ( /* join only with fifteen lowest eligible position values in cat_index */
SELECT *
FROM catalog_category_product_index
WHERE store_id = 1
AND visibility IN(2,4)
AND category_id = 163
ORDER BY position ASC
LIMIT 15
) AS cat_index ON cat_index.product_id = e.entity_id
JOIN catalog_product_index_price price_index
ON price_index.entity_id = e.entity_id
AND price_index.website_id = 1
AND price_index.customer_group_id = 0
GROUP BY e.entity_id /*wrong!!*/
ORDER BY cat_index_position ASC, /* redundant!*/
cat_index.position ASC
LIMIT 15;
It's worth a try.
Are you have sufficient Hardware resources to run a big query and also please update you hardware configuration of server.

SQL - Confusing Query

I have a 'photos' table:
photoID (INT), setID (INT)....
18900 , 234 , ...
18901 , 234 , ...
18902 , 234 , ...
18903 , 249 , ...
18904 , 249 , ...
18905 , 249 , ...
I also have a 'photoKeyword' table:
photoID (INT), keywordID (INT)
18900 , 12
18900 , 21
18901 , 17
18905 , 26
18905 , 10
As you can see from my examples above, photos 18902, 18903 and 18904 do NOT have any keywords in the photoKeyword table. This is exactly what I am trying to establish.
I am trying to produce a list of photoID's that don't have keywords but one setID at a time. So as you can see, photo 18902 doesn't have keywords and so does 18903 and 18904 but these three photos have two different setID's.
So running this query once, should only return photo 18902. I would then add keywords to this photo so it won't be a problem again. The next time I run the query it should return photo 18903 and 18904, the next set (setID:249) of photos that do not have keywords.
How is this possible? Is it possible just using SQL? I hope you can understand what I looking to achieve, I lost myself just writing about it!!
Any thoughts gratefully received...
try
SELECT X.photoID FROM photos X
INNER JOIN
(SELECT DISTINCT P.setID FROM
photos P
LEFT OUTER JOIN (SELECT K.photoID, COUNT(*) C FROM photoKeyword K GROUP BY K.photoID) KC ON KC.photoID = P.photoID
GROUP BY P.setID
HAVING SUM (KC.C) < 1) Y ON X.setID = Y.SetID
SELECT photoID
, setID
FROM photos
WHERE photoID NOT IN
( SELECT photoID
FROM photoKeyword
)
AND setID =
( SELECT setID
FROM photos
WHERE photoID NOT IN
( SELECT photoID
FROM photoKeyword
)
ORDER BY setID
LIMIT 1
)
This might be what you need which is quite simple... when you think about it... Ensure your keyword table has an index on the photo id
select
p.PhotoID,
p.SetID
from
Photos p
LEFT JOIN photoKeyword pkey
on p.PhotoID = pkey.PhotoID
where
pkey.PhotoID = null
By doing a LEFT join, we know it will always attempt to the second table. Then, if the second table has no matches, we know the ID trying to join on will be null... So, left join and return only those IDs where the answer is NULL in the second table.