Having problems writing mysql query joining 4 tables - php

I have a query (which partially works) looking like the following:
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i`,
`cms_dealer_inventory_media` AS `m`,
`cms_dealer_account` AS `a`,
`cms_dealer_setting` AS `s`
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
AND a.inventory_status='1'
AND m.vehicle_id=i.vehicle_id
AND m.type='exterior'
AND a.user_id=i.user_id
AND s.user_id=i.user_id
AND a.country='DE'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
The problem is, the cms_dealer_inventory_media may or may not contain images (bind by vehicle_id). I know the problem is with my WHERE statement in which I am specifically saying m.vehicle_id=i.vehicle_id AND m.type='exterior' but, it causes entries with no images to be ignore.
What I need is a query which makes the m.vehicle_id=i.vehicle_id run IF there are results to cms_dealer_inventory_media.

You should use left join
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i` left join
`cms_dealer_inventory_media` AS `m` on m.vehicle_id=i.vehicle_id
AND m.type='exterior' left join
`cms_dealer_account` AS `a` on a.inventory_status='1'
AND a.user_id=i.user_id AND a.country='DE' left join
`cms_dealer_setting` AS `s` ON s.user_id=i.user_id
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC

If you change your query to use the more modern explicit joins, you could use left joins:
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i`
LEFT JOIN `cms_dealer_inventory_media` AS `m` ON m.vehicle_id=i.vehicle_id
LEFT JOIN `cms_dealer_account` AS `a` ON a.user_id=i.user_id
LEFT JOIN `cms_dealer_setting` AS `s` ON s.user_id=i.user_id
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
AND a.inventory_status='1'
AND m.type='exterior'
AND a.country='DE'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC

you will have to use the join properly
in your case you need all the records from cms_dealer_inventory
so join will be cms_dealer_inventory left outer cms_dealer_inventory_media

Related

How to get multidimensional array from yii 'CDbDataReader::readAll'

It is two tables in a database. The first tablse contains a list of products, and the second contains a list of options. For one product may be several options. I have built next query with yii query bulder
SELECT DISTINCT `p`.`id`,
`p`.`name`,
`pc`.`category_id`,
`c`.`name` AS `category_name`,
`ov`.`value_str` AS `option_value`
FROM `cms_product` `p`
LEFT JOIN `cms_product_category` `pc` ON p.id = pc.product_id
LEFT JOIN `cms_category` `c` ON c.id = pc.category_id
LEFT JOIN `cms_product_option_set` `pos` ON p.id = pos.product_id
LEFT JOIN `cms_option_variant` `ov` ON ov.id=pos.option_variant_id
ORDER BY `p`.`id` ASC LIMIT 100
But yii function 'CDbDataReader::readAll()' returns only one option for each product. If I execute this query in MySQL it works good. How I can get right result with yii
Use queryAll() method like below:
$sql="SELECT DISTINCT `p`.`id`,
`p`.`name`,
`pc`.`category_id`,
`c`.`name` AS `category_name`,
`ov`.`value_str` AS `option_value`
FROM `cms_product` `p`
LEFT JOIN `cms_product_category` `pc` ON p.id = pc.product_id
LEFT JOIN `cms_category` `c` ON c.id = pc.category_id
LEFT JOIN `cms_product_option_set` `pos` ON p.id = pos.product_id
LEFT JOIN `cms_option_variant` `ov` ON ov.id=pos.option_variant_id
ORDER BY `p`.`id` ASC LIMIT 100";
Then:
$result=Yii::app()->db->createCommand($sql)->queryAll();
This will return you an array with the result.

SUM of a secondSELECT statement - PHP - MySQL

I have the following query which works... but I need some changes:
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints
FROM
golf_player p
LEFT JOIN
golf_card gC ON
p.pid = gC.pid
GROUP BY
p.pid
ORDER BY
p.name
DESC
What I really want is another property returned called totalleaguepoints which is a SUM of the most recent 20 league points in my table.
How do I add a limit to a group_concat?
It might be something like this?
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints,
SUM(
SELECT
gC2.leaguepoints
FROM
golf_card gC2
WHERE
gC2.pid = p.pid
ORDER BY
leaguepoints
DESC
LIMIT 20
) AS totalleaguepoints
FROM
golf_player p
LEFT JOIN
golf_card gC ON
p.pid = gC.pid
GROUP BY
p.pid
ORDER BY
p.name
DESC
P.S, the above query does not run
Do you want just the top 20 league points for each player in the group_concat as well as the sum?
If so maybe use user variables:-
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints,
SUM(gC.leaguepoints) AS totalleaguepoints
FROM golf_player p
LEFT JOIN
(
SELECT pid, leaguepoints, #Sequence:=IF(#PrevPid = pid, #Sequence + 1, 0) AS aSequence, #PrevPid := pid
FROM
(
SELECT pid, leaguepoints
FROM golf_card
ORDER BY pid, leaguepoints DESC
) Sub1
CROSS JOIN (SELECT #PrevPid := 0, #Sequence := 0) Sub2
) gC
ON p.pid = gC.pid AND aSequence < 20
GROUP BY p.pid
ORDER BY p.name DESC

SQL multiple joins SELECT query with MAX()

The following query select the subforums from the database and the last posts in each one of them.
SELECT
forums.*,
MAX(posts.id),
posts.title AS lastmsgtitle,
posts.timee AS lastmsgtime,
posts.useraid AS lastmsguseraid,
posts.useradn AS lastmsguseradn,
users.photo AS lastmsgphoto
FROM forums
LEFT JOIN posts
ON(posts.forumid = forums.id)
LEFT JOIN users
ON(posts.useraid = users.id)
WHERE forums.relatedto='$forumid'
and posts.type='post'
GROUP BY forums.id
ORDER BY `id` DESC
The only problem, the query not select the last post, any ideas why?
FORUMS 1
POSTS 2
I would suggest using a subquery to select the max(id) for each post.
SELECT
f.*, -- replace the f.* with the columns that you need to return
p1.MaxId,
p2.title AS lastmsgtitle,
p2.timee AS lastmsgtime,
p2.useraid AS lastmsguseraid,
p2.useradn AS lastmsguseradn,
u.photo AS lastmsgphoto
FROM forums f
LEFT JOIN
(
select MAX(id) MaxId, forumid
from posts
group by forumid
) p1
ON p1.forumid = f.id
LEFT JOIN posts p2
ON p2.forumid = f.id
and p1.MaxId = p2.id
and p2.type='post'
LEFT JOIN users u
ON p2.useraid = u.id
WHERE f.relatedto='$forumid'
ORDER BY `id` DESC

3 sql inner joined tables, now how to count total rows in them

here is the query, I have inner joined 3 tables, Now i am looking to count all rows in the result i.e. 78 by executing query on php my admin, I don't want result of table, i jst want 1 row in wchich only thing written is 78, same as we do in
SELECT count (*) FROM test_table
Below is the query of 3 inner joined tables
SELECT
mybb_users.uid,
mybb_users.username,
mybb_users.avatar,
mybb_posts.fid,
mybb_posts.uid,
mybb_posts.dateline,
mybb_posts.tid,
mybb_posts.subject,
mybb_forums.parentlist,
mybb_forums.fid
FROM mybb_forums
INNER JOIN mybb_posts ON mybb_forums.fid = mybb_posts.fid
INNER JOIN mybb_users ON mybb_posts.uid = mybb_users.uid
WHERE mybb_forums.parentlist LIKE '%58%'
GROUP BY mybb_posts.tid
ORDER BY mybb_posts.dateline DESC
now how to count total number of rows in it ?
EDITED
SELECT count( mybb_users.uid ) AS totalOfRows
FROM (
SELECT mybb_users.uid, mybb_users.username, mybb_users.avatar, mybb_posts.fid, mybb_posts.uid AS uidPost, mybb_posts.dateline, mybb_posts.tid, mybb_posts.subject, mybb_forums.parentlist, mybb_forums.fid AS fidForum
FROM mybb_forums
INNER JOIN mybb_posts ON mybb_forums.fid = mybb_posts.fid
INNER JOIN mybb_users ON mybb_posts.uid = mybb_users.uid
WHERE mybb_forums.parentlist LIKE '%58%'
GROUP BY mybb_posts.tid
)T
Error ::#1054 - Unknown column 'mybb_users.uid' in 'field list'
well, if you don't want the result, why are you showing those fields ? A select return one table, so apply count to it:
SELECT
count(*)
FROM mybb_forums
INNER JOIN mybb_posts ON mybb_forums.fid = mybb_posts.fid
INNER JOIN mybb_users ON mybb_posts.uid = mybb_users.uid
WHERE mybb_forums.parentlist LIKE '%58%'
GROUP BY mybb_posts.tid
Also, you're groupying by posts, so, don't need to order
Edit:
I think the query I've posted should work, anyway, if it's not, this definitely should work:
SELECT sum(Total) AS totalOfRows
FROM (
SELECT 1 as Total
FROM mybb_forums
INNER JOIN mybb_posts ON mybb_forums.fid = mybb_posts.fid
INNER JOIN mybb_users ON mybb_posts.uid = mybb_users.uid
WHERE mybb_forums.parentlist LIKE '%58%'
GROUP BY mybb_posts.tid
)T

How to get total count from query?

this is my query
SELECT a.id,
a.venue_id,
a.user_id,
m1.profilenam AS user_profilename,
m1.photo_thumb AS user_photo_thumb,
m2.profilenam AS venue_profilename,
m2.photo_thumb AS venue_photo_thumb
FROM announce_arrival AS a
INNER JOIN members AS m1
ON a.user_id = m1.mem_id
INNER JOIN members AS m2
ON a.venue_id = m2.mem_id
GROUP BY a.venue_id, a.user_id
LIMIT 0,10
ORDER BY date DESC,
time DESC
How can i use count(*) on this query,i use like this
SELECT DISTINCT COUNT(*)
FROM announce_arrival AS a
INNER JOIN members as m1 ON (a.user_id = m1.mem_id)
INNER JOIN members as m2 ON (a.venue_id= m2.mem_id)
GROUP BY a.venue_id, a.user_id LIMIT 0,10 ORDER BY date DESC,time DESC;
but its showing
COUNT(*)
7
3
1
i want total count .
You can wrap your query into select count(*), like this:
SELECT COUNT(*) FROM
(SELECT a.id,a.venue_id, a.user_id, m1.profilenam as
user_profilename,m1.photo_thumb AS user_photo_thumb,m2.profilenam AS
venue_profilename, m2.photo_thumb AS venue_photo_thumb FROM announce_arrival
AS a INNER JOIN members as m1 ON (a.user_id = m1.mem_id) INNER JOIN members
as m2 ON (a.venue_id= m2.mem_id) GROUP BY a.venue_id, a.user_id)
You can wrap your query in another SELECT:
SELECT COUNT(*) AS total FROM (
SELECT DISTINCT COUNT(*)
FROM announce_arrival AS a
INNER JOIN members as m1 ON (a.user_id = m1.mem_id)
INNER JOIN members as m2 ON (a.venue_id= m2.mem_id)
GROUP BY a.venue_id, a.user_id LIMIT 0,10 ORDER BY date DESC,time DESC) AS t
or if you want sum of all DISTINCT COUNT(*) try:
SELECT SUM(cnt) AS total FROM (
SELECT DISTINCT COUNT(*) AS cnt
FROM announce_arrival AS a
INNER JOIN members as m1 ON (a.user_id = m1.mem_id)
INNER JOIN members as m2 ON (a.venue_id= m2.mem_id)
GROUP BY a.venue_id, a.user_id LIMIT 0,10 ORDER BY date DESC,time DESC) AS t
From docs about found_rows():
To obtain this row count, include a
SQL_CALC_FOUND_ROWS option in the
SELECT statement, and then invoke
FOUND_ROWS() afterward:
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
The second SELECT returns a number
indicating how many rows the first
SELECT would have returned had it been
written without the LIMIT clause.
I.e., add SQL_CALC_FOUND_ROWS after SELECT in your first query and replace second query with SELECT FOUND_ROWS().
Get rid of GROUP BY, LIMIT and ORDER. They are useless and don't make sense (especially LIMIT) if you need a total count. DISTINCT doesn't make sense either.
SELECT COUNT(*)
FROM announce_arrival AS a
INNER JOIN members as m1 ON (a.user_id = m1.mem_id)
INNER JOIN members as m2 ON (a.venue_id= m2.mem_id)
Try this
SELECT COUNT(a.user_id)
FROM announce_arrival AS a
INNER JOIN members as m1 ON (a.user_id = m1.mem_id)
INNER JOIN members as m2 ON (a.venue_id= m2.mem_id)
GROUP BY a.user_id LIMIT 0,10;
If you are using count no need to give order by

Categories