Joining Tables With Zend Framework PHP - php

I am relatively new to the Zend Framework.
I understand the usage of Zend_Table and can obtain data using the Zend functions from the table associated with that class.
For example I have a video table and in another table I have the association between the video and what category it is in.
Im a little stumped how to active a select like the following within the framework:
SELECT * FROM video,category WHERE category.category_id = 3 AND video.id = category.video_id
Any advice would be great.
Thanks.

$db->select()->from('video')->joinInner('category','video.id = category.video_id')->where('category.category_id = ?',3)
BTW: It looks like you have wrong db design. You should have category_id in your video table (if 1 video -> 1 category) or have a connection table (M:N), but it seems wrong to have video id stored in category.

I would use Zend_Db_Select:
$select = $this->db->select()->from(array('v' => 'video'))
->join(array('c' => 'category'),'v.id = c.video_id')
->where('c.category_id = ?', 3);
print_r($select->__toString());
Output:
SELECT `v`.*, `c`.* FROM `video` AS `v` INNER JOIN `category` AS `c` ON v.id = c.video_id WHERE (c.category_id = 3)

Related

Laravel Query Builder - how to format the query using joins

I know this is a poorly written query. How can I re-write this using the Laravel Query builder?
SELECT tgi.rate, tgi.tax_types_id, tt.name, tt.sales_chart_master_id, tt.purchase_chart_master_id
FROM tax_group_items tgi, tax_types tt
WHERE tgi.tax_groups_id = (SELECT tax_groups_id FROM customers WHERE id=2)
AND tt.id = tgi.tax_types_id
AND tt.id NOT IN (SELECT tax_types_id FROM item_tax_type_exemptions WHERE item_tax_types_id = (SELECT item_tax_types_id FROM products WHERE id = 1))
The answer would be more easier and clearer to you if you post your relationships in the model class. If you dont know how to define relations, go to query builder section of official doc.
If you don't want to define relations or don't want to use them then use this
$query = DB::select('your query');
DB::table(DB::raw('tax_group_items tgi, tax_types tt'))
->select(['tgi.rate', 'tgi.tax_types_id', 'tt.name', 'tt.sales_chart_master_id', 'tt.purchase_chart_master_id'])
->whereRaw('tgi.tax_groups_id = (SELECT tax_groups_id FROM customers WHERE id=2)')
->where('tt.id', 'tgi.tax_types_id')
->whereRaw('tt.id NOT IN (SELECT tax_types_id FROM item_tax_type_exemptions WHERE item_tax_types_id = (SELECT item_tax_types_id FROM products WHERE id = 1))')
->get();

Zend Select particular set of columns from multiple tables

Given a query :
SELECT t1.c1, t2.c1 FROM t1,t2;
How to write it in Zend framework without using joins ?
Try the below join query in zend framework,
$sql = $this->tableGateway->getSql()->select();
$sql->join('table2', "table1.column1 = table2.column1", array(column1,column2), 'inner');
Assuming you have a common field (we'll call it c2), you can do something approximating a JOIN without actually doing a JOIN.
// we'll assume $adapter is an instance of Zend_Db_Adapter_Mysqli
$cols = $adapter->fetchAll(
'
SELECT
t1.c1 AS t1c1,
t2.c1 AS t2c1
FROM t1, t2
WHERE t1.c2 = t2.c2
'
);
Using Zend_Db_Select you can do it this way
$rows = $adapter->select()
->from('t1', array('t1c1' => 'c1'))
->from('t2', array('t2c1' => 'c1'))
->where('t1.c2 = t2.c2')
->query()->fetchAll();

How to optimize sub query in kohana

models.php
->add_subquery('(SELECT character_name FROM zid_character_details WHERE character_detail_id = (SELECT character_detail_id from zid_guild_feeds where feed_id = feeds.guild_parent_feed_id)) AS guildcharacter')
->add_subquery('(SELECT character_detail_id FROM zid_character_details WHERE character_detail_id = (SELECT character_detail_id from zid_guild_feeds where feed_id = feeds.guild_parent_feed_id)) AS guildcharacter_id')
->add_subquery('(SELECT character_icon FROM zid_character_details WHERE character_detail_id = (SELECT character_detail_id from zid_guild_feeds where feed_id = feeds.guild_parent_feed_id)) AS guildcharacter_icon')
Above is the three sub-query I am using to take the character_name, character_detail_id & character_icon from zid_character_details table with reference from zid_guild_feeds table.
Can anyone tell me how to optimize this three query into single or simple one.
Thanks
Have a look at Kohana Query Builder Joins and Kohana Query Builder Subqueries
When you need to explore various ORM's, I would advise that you have a look at Leap ORM

Write custom SQL Query in DataObject::get()

I am using Silverstripe version 2.4 . I did not update to new version because I have made many changes and now it is impossible for me to migrate to newer version.
I have a custom SQL query and I want the query to run in DataObject::get();
Here is my Query
SELECT STL.* FROM Page P join SiteTree_Live STL on P.ID = STL.ID join Site S on P.SiteID = S.ID where S.ID = 60 and STL.ShowInMenus = 1 and STL.ParentID = 0 and STL.CanViewType <> 'NotLoggedInUsers' ..
How can I write this query in DataObject::get();
Any help would be greatly appreciated.. Thanks
the easiest way is using the ORM to build that query, in 2.4 it could be done like this (only works if class Site has a has_many to Page, which I assume is the case here):
$site = DataObject::get('Site', 'ID = 60');
// the line below assumes that the has_many in site is called "Pages"
$pages = $site->Pages("ShowInMenus = 1 AND ParentID = 0 AND CanViewType <> 'NotLoggedInUsers'");
alternatively, if you want to save yourself that extra query for Site, you can do it with 1 DataObject::get() using the join parameter. should look something like this:
$pages = DataObject::get(
'Page',
"Site.ID = 60 AND ShowInMenus = 1 AND ParentID = 0 AND CanViewType <> 'NotLoggedInUsers'",
null,
'LEFT JOIN Site ON Site.ID = Page.SiteID'
);

MySQL: Multiple Photos and Videos for News with Joins

I want multiple photos and multiple videos, the main problem is that I can't get them inline if I don't use joins.
So for example, I get 2 photos a video and again a photo.
I have a parent news table and 2 secondary table news_photos and news_videos and I want to get in one query the photos and videos for the news.
Is this somehow possible?
mysql_query("
SELECT *
FROM news_photos, news_videos
FULL JOIN news_videos
ON news_id = {$news_id}
FULL JOIN news_photos
ON news_id = {$news_id}
");
An image about the structure:
There's actually only a single FULL JOIN in that, since you are not involving the news table at all.
SELECT *
FROM news_photos
FULL JOIN news_videos
ON news_photos.news_id=news_videos.news_id
WHERE news_photos.news_id=... OR news_videos.news_id=...
FULL JOIN is not supported by MySQL. It can be less-efficiently simulated using two LEFT JOINs and a UNION, but it's relatively rare that you actually need to. Assuming every photo and video does belong to a news, you could avoid it and get a more conventional query by bringing the news table into it:
SELECT *
FROM news
LEFT JOIN news_photos ON news_photos.news_id=news.id
LEFT JOIN news_videos ON news_videos.news_id=news.id
WHERE news_id=...
But still, this is almost certainly not what you mean! If there are multiple photos and videos for a news item, you would be effectively creating a cartesian product, where every combination of photo and video produces a row. This is the sort of combinatorial explosion you almost never want!
If you just want one of each photo and video, I suppose you could hack that into a single query using a LEFT JOIN that will always give NULL on the other side:
SELECT * FROM news_photos
LEFT JOIN news_videos ON 0
WHERE news_photos.news_id=...
UNION SELECT * FROM news_photos
RIGHT JOIN news_videos ON 0
WHERE news_videos.news_id=...
But there's really nothing to be gained by this. Don't shoehorn two separate queries (“I'd like the photos for a news, and the videos for a news”) into one. Just do it the trivial way:
SELECT * FROM news_photos
WHERE news_id=...
SELECT * FROM news_videos
WHERE news_id=...
i would do it using a stored procedure that had multiple select statements as follows:
http://pastie.org/1141100
drop procedure if exists list_news_photos_videos;
delimiter #
create procedure list_news_photos_videos
(
in p_news_id int unsigned
)
proc_main:begin
select n.* from news n where n.news_id = p_news_id;
select p.* from news_photos p where p.news_id = p_news_id order by photo_id desc;
select v.* from news_videos v where v.news_id = p_news_id order by video_id desc;
end proc_main #
you would call this in mysql as follows:
call list_news_photos_videos(2);
then you can call the stored procedure from php (1 db call only) using mysqli as follows:
http://pastie.org/1141103
<?php
// quick and dirty demo - needs to be made more robust !!
$db = new Mysqli("localhost", "foo_dbo", "pass", "foo_db");
$sql = sprintf("call list_news_photos_videos(%d)", 2); // get all the news related data in one query
$result = $db->query($sql);
//news item
$row = $result->fetch_assoc();
echo sprintf("<h2>news item</h2>news_id = %d subject = %s <br/>", $row["news_id"], $row["subject"]);
$result->free();
//news photos
$db->next_result();
$result = $db->use_result();
echo "<h2>news photos</h2>";
while ($row = $result->fetch_assoc()){
echo sprintf("photo_id = %d subject = %s<br/>", $row["photo_id"], $row["subject"]);
}
$result->free();
//news videos
$db->next_result();
$result = $db->use_result();
echo "<h2>news videos</h2>";
while ($row = $result->fetch_assoc()){
echo sprintf("video_id = %d subject = %s<br/>", $row["video_id"], $row["subject"]);
}
$result->free();
$db->close();
?>

Categories