SELECT from subquery in Codeigniter Active Record - php

How would I do the following query in Codeigniter ActiveRecord : -
SELECT *,
(SELECT
image_path
FROM
image
WHERE
image_table = 'model'
AND image_table_id = model_id
GROUP BY image_table_id
LIMIT 1) AS ModelImg
FROM
(SELECT
*
FROM
vw_newcars
where offer_table = 'derivative'
order by offer_order
) x
WHERE make_name = 'Fiat'
group by offer_table_id
limit 12
The part I'm having problems with is how to do a select from subquery in Active Record.
I don't see a from_select function or anything comparable in the documentation.

I managed to get the query to work by putting the from sub_query into the initial select statement :
$this->db->select("*,
(select image_path from image where image_table = 'model' and image_table_id = model_id
group by image_table_id limit 1) as ModelImg FROM
(SELECT * FROM $view where offer_table = 'derivative' order by offer_order) x");

Related

Mysql query to retrieve single image from an array of images?

Table to store array of Images:
`products` and `products_photos`
`products` includes only `id` field
`products_photos` includes `product_id` and `filename`
Table values:
products
--------
id-6
id-7
products_photos
---------------
6 - filename1
6 - filename2
7 - filename3
In these two table id 6 includes 2 images but i need to fetch only one image from that. How to write a query for that in mysql or laravel.
If you want to get the latest (last added) image of the product then you can do the following way
NOTE : Instead of *, use the precise columns so that your query performs faster.
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY products_photos.id DESC LIMIT 1;
If you want to get the first (old added) image of the product then you can do the following way
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY products_photos.id ASC LIMIT 1;
Updated : Query to get the list of all the records group
SELECT MAX(id) as id, photo_name FROM products_photos GROUP BY photo_name
In case if you have more than one columns and want to get the latest record for that too then go for this
Eg. Considering that your having description column and want to get the MAX (latest) content than use MAX, if you need oldest use MIN
SELECT MAX(id) as id, photo_name, MAX(description) as description FROM products_photos GROUP BY photo_name
You can give limit to your query to get single result
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY id LIMIT 1;
Which will give single image only for id = 6 product
For retrieve all data use group by
SELECT * FROM GemSellerPortal.products pr
LEFT JOIN GemSellerPortal.products_photos ph
ON ph.product_id = pr.id
GROUP BY pr.id

mysql update subquery not working

mysql update syntax doesn't seem to work when I added the subquery.
Are there restrictions on subqueries on update syntax?
doesn't work:
update books set imagename ='name'
where book_ID='(select book_ID from books order by book_ID desc limit 1)';
works:
update books set imagename ='name'
where book_ID='101';
MySQL does have limits on subqueries using the table being updated. So yours is not allowed:
update books
set imagename ='name'
where book_ID = (select book_ID from books order by book_ID desc limit 1);
Instead, you can do:
update books
set imagename ='name'
order by book_ID desc
limit 1;
Here is the explanation in the documentation:
In general, you cannot modify a table and select from the same table
in a subquery. For example, this limitation applies to statements of
the following forms:
DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
{INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
Exception: The preceding prohibition does not apply if you are using a subquery for the modified table in the FROM clause. Example:
UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);
Here the result from the subquery in the FROM clause is stored as a temporary table, so the relevant rows in t have already been
selected by the time the update to t takes place.
Try This query.
Update books
Set imagename = name"
Where book_ID In (
Select T1.book_ID
From books As T1
Where T1.book_ID = '101'
)

SQL - concatenate results from 2 tables

First I need to get exact match like
SELECT * FROM movies WHERE title='STRING' ORDER BY x DESC
and then append to these results query with LIKE match
SELECT * FROM movies WHERE title LIKE '%STRING&' AND title<>'STRING' ORDER BY x DESC
and limit these results with maximum of 10 results.
UNION wont`t do the jobs as it sorts all results together and returns wrong order (I need exact match first, then with LIKE)
SELECT * FROM movies WHERE title='STRING' UNION
SELECT * FROM movies WHERE title LIKE '%STRING%' ORDER BY x DESC LIMIT 10
The best solution I got is to use multi_query()
$query = "SELECT * FROM movies WHERE title='STRING' ORDER BY x DESC; ";
$query .= "SELECT * FROM movies WHERE title LIKE '%STRING%' AND title<>'red' ORDER BY x DESC";
$Dbi->multi_query($query);
do {
$sql = $Dbi->store_result();
while($x = $sql->fetch_array()) {
...
}
} while($Dbi->next_result());
but in this case it is not possible to use any mysql inside the inner loop and there also must be better looking solution!
You can do this with one query, by using the order by clause:
SELECT *
FROM movies
WHERE title like '%STRING%'
ORDER BY title = 'STRING' desc,
title like '%STRING%' desc
LIMIT 10;
The first clause in the ORDER BY puts the exact matches first. The second then orders by the partial matches. The WHERE clause ensures that there is a match of some kind.
You don't need the UNION, it's accessing the same table twice:
SELECT *
FROM movies
WHERE title LIKE '%STRING&'
ORDER BY CASE WHEN title='STRING' THEN 1 ELSE 2 END
LIMIT 10
(SELECT * FROM movies WHERE title='STRING')
UNION
(SELECT * FROM movies WHERE title LIKE '%STRING%' ORDER BY x DESC LIMIT 10)

Sorting mysql results by times from 3 tables

I have 3 tables: questions, articles and pictures
The rows in each table contain a current_timestamp column posted, and link to an id. I'd like to sort the results of the rows of all three by their timestamp and only echo the newest of the three (for example: if the question is newest from the ID, display that only)
if(count($interests) != 0){ foreach($interests as $interests_following){
$interestid = mysql_result(mysql_query("SELECT `id` FROM `interests` WHERE `name` = '$interests_following'"),0);
$interestquestions = #mysql_result(mysql_query("SELECT `question_text`, `posted` FROM `questions` WHERE `interest` = '$interests_following'"),0);
$interestarticles = #mysql_result(mysql_query("SELECT `article_title`, `posted` FROM `articles` WHERE `interest_id` = '$interestid'"),0);
$interestpictures = #mysql_result(mysql_query("SELECT `interest_pic_title`, `posted` FROM `interest_pictures` WHERE `interest_id` = '$interestid'"),0);
echo '.$interests_following.': //<Only display 1 newest item (article/picture/question here>
Use UNION ALL:
SELECT posted
FROM
(
SELECT `question_text`, `posted` FROM `questions`
WHERE `interest` = '$interests_following'
UNION ALL
SELECT `article_title`, `posted` FROM `articles`
WHERE `interest_id` = '$interestid'
UNION ALL
SELECT `interest_pic_title`, `posted` FROM `interest_pictures`
WHERE `interest_id` = '$interestid'
) t
ORDER BY posted DESC LIMIT 1
To get a single row back:
$sql = "SELECT * FROM WHERE `name`='$interests_following' ORDER BY `posted` DESC LIMIT 1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
All of the work is in the SQL
ORDER BY `posted` DESC LIMIT 1
This orders results to have the newest first, then only return the first row.
If you mean to return only one item out of the 3 tables, you have 2 choices:
Fetch a row from each and then determine the newest in PHP
Use a UNION to find the single newest row in SQL
The latter makes for less code, but will probably be less readable.
try this
$interestquestions = #mysql_result(mysql_query("SELECT `question_text`, `posted` FROM `questions` WHERE `interest` = '$interests_following' ORDER BY timestamp_field DESC limit 1"),0);
this will show only the latest data base on your timestamp.
I'll show you the SQL queries so you can see what I did; adapt it to your code as needed.
SELECT
(SELECT question_text
FROM questions ORDER BY posted DESC LIMIT 1 ),
(SELECT article_title
FROM articles ORDER BY posted DESC LIMIT 1 ),
(SELECT interest_pic_title
FROM interest_pictures ORDER BY posted DESC LIMIT 1)
;
This sorts by the timestamp DESCending, so the latest record is first, then limits it to the single record. The result will be question_text, article_title, interest_pic_title.

Advanced SQL query. Top 12 from each category (MYSQL)

I have a MYSQL5 database and PHP 5. I need a query for a games websites index page that only selects the first 12 from each category of games. Here is what I have so far.
$db->query("SELECT * FROM `games` WHERE status = 'game_published' AND `featured` = '1' ORDER BY `category`");
The php code then groups games of the same category together and displays them. But yeah it doesn't limit the number of games from each category like I want.
Here is exactly what the structure of the table looks like: i49.tinypic.com/aysoll.png
Here is a blog post which sounds like what I am trying to do: http://www.e-nformation.net/content/view/title/MySQL+Top+N+in+each+group+(group+inner+limit) But I can't make sense of it.
Any help is appreciated.
How about this?
SELECT * FROM (
SELECT
games.*,
#rn := CASE WHEN #category=category THEN #rn + 1 ELSE 1 END AS rn,
#category := category
FROM games, (SELECT #rn := 0, #category := NULL) AS vars
WHERE status = 'game_published' AND featured = '1'
ORDER BY category
) AS T1
WHERE rn <= 12
you could use UNION, if we are not talking about million of types...
pseudoSQL:
(SELECT * FROM table WHERE condition AND category = 'action' ORDER BY id LIMIT 10)
UNION
(SELECT * FROM table WHERE condition AND category = 'action' ORDER BY id LIMIT 10)
UNION
(SELECT * FROM table WHERE condition AND category = 'action' ORDER BY id LIMIT 10)
If you have array of categories in your PHP/ASP, you can generate this union on the fly.
More:
http://dev.mysql.com/doc/refman/5.0/en/union.html
EDIT:
Here's probably most useful resource: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Use it well ^^
There may be a more elegant solution, but you can just execute a query for each category. First get a list of categories:
SELECT DISTINCT(category) FROM `games`;
Then take each of the results and query for 12 rows:
SELECT * FROM games WHERE status = 'game_published'
AND `featured` = '1' AND `category` = $category LIMIT 12;
Of course you need to add some kind of ranking row (and order by it) to get the top 12.
Note: There may be a way to do this with a single query, but it escapes me at the moment.
To use the technique from the posts you mention, you need a way to order the games. They're using article date. Then they select the number of older articles for that company, and say there can't be more than three.
If your games table has an auto-increment column called id, you can select the top 10 games per category like:
SELECT *
FROM games g1
WHERE status = 'game_published'
AND featured = '1'
AND 10 >
(
SELECT COUNT(*)
FROM games g2
WHERE g2.status = 'game_published'
AND g2.featured = '1'
AND g1.category = g2.category
AND g2.id > g1.id
)
The where condition says that there can't be more than 10 rows with the same category and a higher ID.

Categories