I'm trying to combine two bits of logic into one SQL query to speed up the effectiveness of my codebase, I currently have the two queries like so (pseudo code):
// Looping each user in table
$statement = "SELECT id FROM users";
// I then loop that statement, combining data from sub-query
{
// Get the "summing" data from table in reference to looped user
$second_statement = "SELECT add_col_1,add_col_2FROM users WHERE ref = id"
// Combine add_col_1, and add_col_2 together
array_sum($second_statement)
}
What I am after is the sum of that second statement, getting the ID from the first query SELECT id FROM users then researching that table for a reference to that, under the column name ref where I can then add together columns from each of those rows.
I'm not doing this so that I can get one statement instead of two, it's cause once the app scales, having to query thousands of users exponentially is just not good.
The statement I attempted to unite these two loops is:
SELECT
id,
(SUM(SELECT col_add_1+col_add_2 FROM users WHERE ref = a.id)) AS total
FROM users a
Got an execution error.
nearly there, you just need to join to itself to link up all the items in one call then group the results by id so the sum works on all the linked items.
SELECT
a.id,
SUM(b.col_add_1 + b.coll_add_2)
FROM
users a
LEFT JOIN
users b
ON
a.id = b.ref
GROUP BY
a.id
You have got an error because you are performing aggregation without involving any group by clause. So, you should re-write your query as
SELECT id,
(SELECT SUM(col_add_1+col_add_2) FROM users WHERE ref = a.id) AS total
FROM users a
GROUP BY id;
Related
I am having relational database and trying to execute following query up to 3 tables It is giving me correct results i.e. 248 records of students in institute id 910, but when I try to make a query having more than 3 tables it gives me 19000+ results.
SELECT *
FROM Student,StudentRegistration,RefStudentType,RefGender,SubjectCategory
WHERE Student.student_id=StudentRegistration.student_student_id
AND StudentRegistration.reg_student_type_std_type_id = RefStudentType.std_type_id
AND Student.student_gender_gender_id = RefGender.gender_id
AND StudentRegistration.reg_student_subjectCat_sub_cat_id=SubjectCategory.sub_cat_id
AND Student.student_institute_inst_id=910;
`
Tried with JOIN as well but same 19000+ records incorrect results
SELECT * FROM Student INNER JOIN StudentRegistration ON student_id=student_student_id INNER JOIN RefReligion ON RefReligion.religion_id=Student.student_religion_religion_id INNER JOIN RefStudentType ON RefStudentType.std_type_id=StudentRegistration.reg_student_type_std_type_id WHERE student_institute_inst_id=910;
Any solution, query logical errors or something new
I think this is due to having several records for one data. For example, there might be several records in the SubjectCategory table for id = '910'
It is best to use left/right/inner/outer joins without using from tbl1, tbl2
What I suggest is to check the tables one by one with the id.
I have two mysql tables. And essentially two queries (one to each table) that I want to combine within a single SQL Query. Seems like it should be easy (kind of like an inner Join) But inner join is DUPLICATING non-uniqe values from table 2 into my results array... I dont want them duplicated... I want those duplicates from table/query 2 combined into the result record of query1
Query 1 Gets records from table 1. Results are unique. (one ID returns one record) It's simply returning all fields on records where an ID is equal to one of my conditions. [Im using IN instead of a bunch of OR's)
$sid = "'M-179','M-242','M-231','Q-2thru5'" ;
$query = "SELECT * FROM table1 WHERE IN ($sid)`
Query 2 gets records from table 2. But results are NOT unique. One ID can return many records.
$query2 = "SELECT extra_data, pub_url FROM table2 WHERE IN ($sid)";
So I want EACH extra_data & pub_url field from ALL returned records just slapped onto the end of the query 1 result. Am I making sense? So the result would look something like this...
[0] => Array
(
* all my returned fields from the
record returned by query 1 here
$row['extra_data']
$row['pub_url'] <-returned record from query 2
$row['extra_data']
$row['pub_url'] <-another returned record from query 2
$row['extra_data']
$row['pub_url'] <-any another returned
record from query 2, etc..
)
What do you mean by combining the result?
Do you want the results from query2 to appear in the same
relevant rows but just extra columns, or you want them to
appear as new rows.
For the first case, you will have to use JOIN.
But I have a feeling that what you want to do is the second
case. In this case, you will have to use UNION. Note, however,
that in this case the columns of the two queries must match. So
the union of two queries would look like this:
-- pseudo code only
SELECT extra_data, pub_url FROM table1 WHERE IN ($sid)
union
SELECT extra_data, pub_url FROM table2 WHERE IN ($sid)
Try something similar to this, which would join the results of table 1 to table 2 on the column containing the sid value.
SELECT a.*, b.extra_data, pub_url
FROM table1 a
left outer join table2 b on a.sid = b.sid
WHERE a.sid IN ($sid)
I have two tables : items and comments.
I want to select all items which a user commented on.
For simplicity, lets assume the items table has two columns : item_id and item_content. Let the comments table have 3 columns user_id, item_id and comment_content.
I am given the user_id of the commenting user, I need to first select all the item_id from the comments table, where user_id = myUserId.
This is a basic query SELECT item_id FROM comments WHERE user_id = '$myUserId'.
Then I need to select the item_content for each item_id returned by the previous query.
I was thinking of doing a while($row = $my_first_query->fetch_array()) loop, and inside of it doing something like SELECT item_content FROM item WHERE item_id = $row["item_id"]
however this is a bit messy and I was wondering if there was a simpler way of doing this, by combining the two queries into one.
Use an INNER JOIN:
SELECT t1.*
FROM items t1
INNER JOIN comments t2
ON t1.item_id = t2.item_id
WHERE t2.user_id = myUserId
The approach you suggested of first querying the comments table and then looping over the result set is inefficient. In a join, MySQL can handle this algebra much faster than your PHP code.
Depending of what you want to do exactly, you can just use a JOIN clause. The "header" table info will be found within all rows, so it might not be what you want to do.
Another way would be to run two distinct queries, the first one unchanged and the second one with a join. You would then have one result with the header, and the other with all the details that you could go through. It's more performant than run the same query over and over network wise.
I have 3 tables they are...
posts_deletedPosts
posts_archivedPosts
posts_newPosts
I am writing a function which allows users to see all of their posts and so I want to do a join query to pull all the data from these three tables back in one query.
All three tables has the exact same columns I want to get back, and they are...
title
category
dateCreated
alias
The query i've written so far I think should work, but when I go to use bind param I get this error.
Warning: mysqli_stmt::bind_result() [mysqli-stmt.bind-result]: Number of bind variables doesn't match number of fields in prepared statement
My query looks like as follows...
$stmt = $this->conx->prepare("SELECT
dp.title, dp.category, dp.dateCreated, dp.alias,
ap.title, ap.category, ap.dateCreated, ap.alias,
np.title, np.category, np.dateCreated, np.alias
FROM posts_deletedPosts AS dp
INNER JOIN posts_archivedPosts AS ap
ON dp.author = ap.author
INNER JOIN posts_newPosts AS np
ON dp.author = np.author
WHERE dp.author = ?
LIMIT 5");
I'm pretty new to web dev but I thought it would be possible to carry out a join like this and return one large dataset. I did use 3 select queries before but I want to build some pagination using AJAX and so I need this data in one complete set preferably.
This is how i bind the parameter
$stmt->bind_param("i",$uid);
You don’t need JOINs, you need UNIONs:
SELECT title FROM posts_deletedPosts WHERE author=...
UNION
SELECT title FROM posts_archivedPosts WHERE author=...
UNION
SELECT title FROM posts_newPosts WHERE author=...
I've been racking my brain for hours trying work out how to join these two queries..
My goal is to return multiple venue rows (from venues) based on certain criteria... which is what my current query does....
SELECT venues.id AS ven_id,
venues.venue_name,
venues.sub_category_id,
venues.score,
venues.lat,
venues.lng,
venues.short_description,
sub_categories.id,
sub_categories.sub_cat_name,
sub_categories.category_id,
categories.id,
categories.category_name,
((ACOS( SIN(51.44*PI()/180)*SIN(lat*PI()/180) + COS(51.44*PI()/180)*COS(lat*PI()/180)*COS((-2.60796 - lng)*PI()/180)) * 180/PI())*60 * 1.1515) AS dist
FROM venues,
sub_categories,
categories
WHERE
venues.sub_category_id = sub_categories.id
AND sub_categories.category_id = categories.id
HAVING
dist < 5
ORDER BY score DESC
LIMIT 0, 100
However, I need to include another field in this query (thumbnail), which comes from another table (venue_images). The idea is to extract one image row based on which venue it's related to and it's order. Only one image needs to be extracted however. So LIMIT 1.
I basically need to insert this query:
SELECT
venue_images.thumb_image_filename,
venue_images.image_venue_id,
venue_images.image_order
FROM venue_images
WHERE venue_images.image_venue_id = ven_id //id from above query
ORDER BY venue_images.image_order
LIMIT 1
Into my first query, and label this new field as "thumbnail".
Any help would really be appreciated. Thanks!
First of all, you could write the first query using INNER JOIN:
SELECT
...
FROM
venues INNER JOIN sub_categories ON venues.sub_category_id = sub_categories.id
INNER JOIN categories ON sub_categories.category_id = categories.id
HAVING
...
the result should be identical, but i like this one more.
What I'd like to do next is to JOIN a subquery, something like this:
...
INNER JOIN (SELECT ... FROM venue_images
WHERE venue_images.image_venue_id = ven_id //id from above query
ORDER BY venue_images.image_order
LIMIT 1) first_image
but unfortunately this subquery can't see ven_id because it is evaluated first, before the outer query (I think it's a limitation of MySql), so we can't use that and we have to find another solution. And since you are using LIMIT 1, it's not easy to rewrite the condition you need using just JOINS.
It would be easier if MySql provided a FIRST() aggregate function, but since it doesn't, we have to simulate it, see for example this question: How to fetch the first and last record of a grouped record in a MySQL query with aggregate functions?
So using this trick, you can write a query that extracts first image_id for every image_venue_id:
SELECT
image_venue_id,
SUBSTRING_INDEX(
GROUP_CONCAT(image_id order by venue_images.image_order),',',1) as first_image_id
FROM venue_images
GROUP BY image_venue_id
and this query could be integrated in your query above:
SELECT
...
FROM
venues INNER JOIN sub_categories ON venues.sub_category_id = sub_categories.id
INNER JOIN categories ON sub_categories.category_id = categories.id
INNER JOIN (the query above) first_image on first_image.image_venue_id = venues.id
INNER JOIN venue_images on first_image.first_image_id = venue_images.image_id
HAVING
...
I also added one more JOIN, to join the first image id with the actual image. I couldn't check your query but the idea is to procede like this.
Since the query is now becoming more complicated and difficult to mantain, i think it would be better to create a view that extracts the first image for every venue, and then join just the view in your query. This is just an idea. Let me know if it works or if you need any help!
I'm not too sure about your data but a JOIN with the thumbnails table and a group by on your large query would probably work.
GROUP BY venues.id