php mysql inner join - get a particular row - php

This is my query to get model information from one table and a single picture from another table. What changes do I have to make to this query in order for it to get the picture where ORDER BY sort DESC? In the table of the pictures, there is a field by the name "sort". The default value for the field for each row is 0. But one random row has the value of 1. I want to get that particular row. I don't, however, want to use WHERE sort=1 because then even in the case where no row has the sort value 1, one row should still get fetched.
$sql="SELECT tc.id,tc.alias,tc.firstname,tci.imagename
FROM ".$pre."models tc
INNER JOIN ".$pre."model_images tci ON tc.id=tci.userid
WHERE activated=1 AND sex=$sex AND city=$city AND published=1
GROUP BY tc.id ORDER BY firstname ASC";
Thank you in advance!
Solved using:
SELECT tc.id,tc.alias,tc.firstname,
(SELECT imagename FROM ".$pre."model_images WHERE userid= tc.id
ORDER BY sort DESC LIMIT 1) AS imagename
FROM ".$pre."models tc
WHERE tc.activated=1 AND tc.sex=1 AND tc.city=2 AND tc.published=1
ORDER BY tc.firstname ASC

You should place that in your WHERE clause aswell. One t hing to note though is to be carefull with the way you're using the column names. It's better to tell to which table they belong.
So this:
WHERE activated=1 AND sex=$sex AND city=$city AND published=1
Should be:
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1
And then simply add the 'sort' column to it:
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1 AND tci.sort=1
If no results are returned, then make sure that there are records that meet the required conditions. Because there's nothing wrong with the query. Try to print your query to the screen etc. to see if every variables has a value.
edit:
You should lose the GROUP BY.
SELECT tc.id,tc.alias,tc.firstname,tci.imagename
FROM ".$pre."models tc
INNER JOIN ".$pre."model_images tci ON tc.id=tci.userid
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1 AND tci.sort=1

Related

How to retrieve nested join select statement data from query

I have the following query and am unsure of how to retrieve the 'note' from the nested join query.
This Left join selects the latest note for this customer, but I am not sure how to echo this data...
LEFT JOIN (SELECT note AS latestnote, timestamp, renewalid FROM renewal_note ORDER BY timestamp DESC LIMIT 1) AS n ON n.renewalid=renewal.id
Full Query:
SELECT renewal.id AS rid, renewal.personid, renewal.enddate, renewal.assettype, renewal.producttype, renewal.vrm, renewal.make, renewal.model, renewal.submodel, renewal.derivative, renewal.complete, person.forename, person.surname, person.company, appointment.id AS appid, appointment.renewalid,
(SELECT COUNT(complete) FROM renewal WHERE complete=1 && enddate BETWEEN '".$month_start."' AND '".$month_end."' && dealershipid='".$dealership_id."' && assettype='U' && producttype!='CH' && complete=1) AS renewedcount
FROM renewal
LEFT JOIN person ON person.id=renewal.personid
LEFT JOIN appointment ON appointment.renewalid=renewal.id
LEFT JOIN (SELECT note AS latestnote, timestamp, renewalid FROM renewal_note ORDER BY timestamp DESC LIMIT 1) AS n ON n.renewalid=renewal.id
WHERE enddate BETWEEN '".$month_start."' AND '".$month_end."' && renewal.dealershipid='".$dealership_id."' && assettype='U' && producttype NOT LIKE '%CH%'
ORDER BY enddate ASC
The Below is currently what is returned in each loop (which is working fine), and I can access as normal; $row['COLUMNNAME'].
rid
personid
enddate
assettype
used/new
producttype
vrm
make
model
submodel
derivative
complete
forename
surname
company
appid
renewalid
renewedcount
BUT I also need to be able to get the NOTE from renewal_note (the third LEFT JOIN).
I dont have issues with normal inner joins, But I have never created a query with subqueries, so struggling to echo this data out within the php loop.
(Just to point out that the only reason I am nesting a query is that I need only the latest note for each customer to be returned.)
I have tried $row['latestnote'], (with no success) and I am sure this is definitely not the way to access this data.
Could someone please point me in the right direction?
UPDATE
With updates from the comments, I have tried a much more simplified query (with ALL columns included so can't miss anything out) specifically targetting the subquery:
SELECT
*
FROM
renewal
LEFT JOIN(
SELECT
*
FROM
renewal_note
ORDER BY
TIMESTAMP
DESC
LIMIT 1
) AS n
ON
n.renewalid = renewal.id
But this still returns NULL for every column on the renewal_note.
90% of 'renewal' records have a note linked to them in the renewal_note table, but none showing.
renewal table has a unique primary key; ID.
renewal_note table links via column name: renewalid.
I think I have sussed this out.
Thanks to the commenters :)
Purely posting this for anyone else with similar questions/issues.
To get data from a LEFT JOIN(SELECT... statement; include the alias into the outer SELECT statement. Then you can use $row['columnname'] as normal.
LIMIT 1 on the subquery returned only 1 record for the entire query. Remove LIMIT 1 to show all results for the subquery dependant on your 'link' to the main query.
From what I have tested, ORDER BY seems to be working, but not sure if this is a fluke, or if it just sorting naturally by the primary key; ID

How to show repeated row one time mysql?

Here is
I want to show rows with same stop name one time..
How i use Query and While Loop
I see you have and id column. Assuming that it is unique you can do this all in sql query, no need for while loop.
You will need 2 queries; first will get the maximum (could be minimum also) available id of only one distinct stop name, the second is a join query with the first results and the main table. Something like this:
select * from tablename
inner join
(
select stop, max(id) as id from tablename
group by stop
)
as uniqueIDs
on tablename.id=uniqueIDs.id
u may try this..this will help you to fetch duplicates from table
SELECT tablename.stop FROM tablename INNER JOIN
(SELECT stop FROM tablename GROUP BY stop HAVING COUNT(id) > 1) dup
ON tablename.stop = dup.stop;

SUM value from query changes when i add inner join to the query

$sql = mysql_query("SELECT totals.*, sum(totals.payments) as total_payments
FROM totals
INNER JOIN users
GROUP BY totals.idseller;");
When i add the INNER JOIN the sum value is changed. Why?
In my SQL table i have one record in totals width this value: 8943.09 but when i do the some the result is giving me this value: 44715.45
What i am doing wrong?
$sql = mysql_query("SELECT totals.*, sum(totals.payments) as total_payments FROM totals
INNER JOIN users ON totals.idseller = users.idseller
GROUP BY users.UserName;");
Use this Hope this will help you.
When you INNER JOIN to another table, the returned data set is modified to only include rows that exist in both tables. In this case it is likely that there are rows in 'totals' that do not have a matching row in users - either the totals.idseller field might accept null values, or data has become orphaned when matching users have been deleted or edited.
If you want all data in 'totals' regardless of matching user you would user a LEFT JOIN instead in ms-sql, I suspect a similar approach will work in my-sql
You should give an "on" based on the ids. Such as like
inner join users on users.id = totals.idseller
Otherways the sql server will combine all possible rows in the tables, which is most cases not what you wish.
Because when you are adding inner join in your SQL Query, it means you are selecting the data which is common in both the tables.
EX:
SELECT * FROM TABLE_A
INNER JOIN TABLE_B
ON TABLE_A.ID = TABLE_B.ID
If you are joining users table which contains 5 records. By joining table, as there is no any column mapping, this sum-up 5 times and this is reason for showing different values.
Please let me know something wrong in it.
Thanks,
Umehs

MySql - Joining another table with multiple rows, inserting a query into a another query?

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

Mysql - How to get a row number after Order by?

Let's say I have a table with the following columns:
p_id
userid
points
Let's say these columns have over 5000 records. So we actually have users with points. Each user has an unique row for their point record. Imagine that every user can get points on the website by clicking somewhere. When they click I update the database with the points they get.
So we have a table with over 5000 records of people who have points, right? Now I would like to order them by their points (descending), so the user with the most point will be at the top of the page if I run a MySQL query.
I could do that by simply running a query like this:
SELECT `p_id` FROM `point_table` ORDER BY `points` DESC
This query would give me all the records in a descending order by points.
Okay, here my problem comes, now (when it is ordered) I would like to display each user which place are they actually. So I'd like to give each user something like this: "You are 623 of 5374 users". The problem is that I cannot specify that "623" number.
I would like to run a query which is order the table by points it should "search" or count the row number, where their records are and than return that value to me.
Can anyone help me how to build a query for this? It would be a really big help. Thank you.
This answer should work for you:
SET #rank=0;
SELECT #rank:=#rank+1 AS rank, p_id FROM point_table ORDER BY points DESC;
Update: You might also want to consider to calculate the rank when updating the points and saving it to an additional column in the same table. That way you can also select a single user and know his rank. It depends on your use cases what makes more sense and performs better.
Update: The final solution we worked out in the comments looked like this:
SELECT
rank, p_id
FROM
(SELECT
#rank:=#rank+1 AS rank, p_id, userid
FROM
point_table, (SELECT #rank := 0) r
ORDER BY points DESC
) t
WHERE userid = intval($sessionuserid);
Row number after order by
SELECT ( #rank:=#rank + 1) AS rank, m.* from
(
SELECT a.p_id, a.userid
FROM (SELECT #rank := 0) r, point_table a
ORDER BY a.points DESC
) m
For some reason the accepted answer doesn't work for me properly - it completely ignores "ORDER BY" statement, sorting by id (primary key)
What I did instead is:
SET #rn=0;
CREATE TEMPORARY TABLE tmp SELECT * FROM point_table ORDER BY points DESC;
SELECT #rn:=#rn+1 AS rank, tmp.* FROM tmp;
Add a new column for position to the table. Run a cron job regularly which gets all the table rows ordered by points and then update the table with the positions in a while loop.

Categories