My current SQL is:
SELECT * FROM `node`
LEFT JOIN `field_data_field_area_of_study_category`
ON `field_data_field_area_of_study_category`.`entity_id` = `node`.`nid`
WHERE `node`.`type` = 'area_of_study'
GROUP BY `node`.`nid`
For now, to make it work I run a foreach loop to is_null() on the column.
I'm trying to emulate the is_null() check within the SQL query.
Thanks for reading.
EDIT
This is the foreach loop that runs the is_null(). I think a better way to ask my question would be: how do make the SQL return only rows from the node table where there is no matching field_data_field_area_of_study_category table?
foreach($aos_nodes as $aos_node):
if (is_null($aos_node->field_area_of_study_category_tid)):
$menu_item_display[$aos_node->title] = array(
'id' => $aos_node->nid,
'type' => 'node',
'children_markup' => '',
'icon' => '',
'name' => $aos_node->title,
'href' => drupal_get_path_alias('node/'.$aos_node->nid),
);
endif;
endforeach;
To return the rows where there isn't a matching one:
SELECT * FROM `node`
LEFT JOIN `field_data_field_area_of_study_category`
ON `field_data_field_area_of_study_category`.`entity_id` = `node`.`nid`
WHERE `node`.`type` = 'area_of_study'
and `field_data_field_area_of_study_category`.`entity_id` is null
GROUP BY `node`.`nid`
Additionally, you can use not exists:
select
*
from
node n
where
n.type = 'area_of_study'
and not exists (
select
1
from
field_data_field_area_of_study_category f
where
f.entity_id = n.nid
)
Related
I had two tables
ads
adImages
here table ads id and table adImages adsId are same. here i have to select all the rows from the table ads and adImages, and display it in json format.
My codes looks:
$query="SELECT a.*, b.images FROM `ads` AS a INNER JOIN `adImages` AS b ON a.id = b.adsId";
$result=mysql_query($query);
$value = mysql_num_rows($result);
if($value>=1)
{
while($row = mysql_fetch_array($result))
{
$details[] = array(
'id' => $row['id'],
'location' => $row['location'],
'title'=>$row['title'],
'mobile' => $row['mobile'],
'description' => $row['description'],
'category' => $row['category'],
'images' =>'http://greenwma.com/dev/uploads/'.$row['images'],
);
}
echo json_encode($details);
}
And its output json looks like :
[{"id":"10","location":"9.982852,76.300637","title":"Ggg","mobile":"5555555","description":"Google","category":"BusMedia","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016062319:07:39.jpg{"id":"10","location":"9.982852,76.300637","title":"Ggg","mobile":"5555555","description":"Google","category"BusMedia","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 17:27:05.jpg"},{"id":"11","location":"9.962439,76.305337","title":"Test","mobile":"898566899","description":"Test","category":"Bus Shelters","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:15:16.jpg"},{"id":"11","location":"9.962439,76.305337","title":"Test","mobile":"898566899","description":"Test","category":"Bus Shelters","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:08:50.jpg"},{"id":"11","location":"9.962439,76.305337","title":"Test","mobile":"898566899","description":"Test","category":"Bus Shelters","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:07:39.jpg"}]
here the problem is id,location,title,mobile,description,category are repeating for each image on same adsId.
And my need is that, I have to get json in the format
[{"id":"10","location":"9.982852,76.300637","title":"Ggg","mobile":"5555555","description":"Google ","category":"Bus Media","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:07:39.jpg","http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 17:27:05.jpg"},{"id":"11","location":"9.962439,76.305337","title":"Test","mobile":"898566899","description":"Test","category":"Bus Shelters","images":"http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:15:16.jpg","http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:08:50.jpg","http:\/\/greenwma.com\/dev\/uploads\/MapCapture2016-06-23 19:07:39.jpg"}]
that is, I have to get all images separated by comma in single json object. for that what all changes should I make in the above code.
You can use CONCAT() & GROUP_CONCAT() with sub queries to do it in one query and lesser loops.
SELECT a.*, GROUP_CONCAT(images) images FROM (
SELECT a.*, CONCAT('http://greenwma.com/dev/uploads/', b.images) images
FROM `ads` AS a
INNER JOIN `adImages` AS b ON a.id = b.adsId
) tbl
GROUP BY id
I have this code running
$sq = $this->_codes->getAdapter()->select()
->from (array('cs' => 'code_statuses'), array('total' => 'count(*)'))
->join (
array ('c' => 'codes'), 'c.code_id = cs.code_id',
array ('human_state' => new Zend_Db_Expr("CASE c.state_id WHEN 3 THEN 'active' WHEN 5 THEN 'suspended' ELSE 'inactive' END"), 'c.*')
)
->group('cs.code_id');
$sqtemp = $this->_codes->getAdapter()->select()
->from (array('cs' => 'code_statuses'), array('total' => 'count(*)'))
->join (
array ('c' => 'codes'), 'c.code_id = cs.code_id',
array ('human_state' => new Zend_Db_Expr("CASE c.state_id WHEN 3 THEN 'active' WHEN 5 THEN 'suspended' ELSE 'inactive' END"), 'c.*')
)
->group('cs.code_id');
if (!empty($options['state_id'])):
if (is_array($options['state_id'])):
$states = 'cs.state_id=' . implode(' OR cs.state_id=', $options['state_id']);
$sq->where($states)
->having(total<=4);
$sqtemp->where ('cs.state_id=5')
->having(total<4);
else:
$sq->where ('cs.state_id=?', $options['state_id']);
endif;
The issue occurs when i try to use union
$sqfinal=$this->_codes->getAdapter()->select()
->union(array($sq,$sqtemp))
->order('cs.code_id');
but individually $sq and $sqtemp work fine
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'cs.code_id' in 'order clause'
Not sure where I am going wrong
Any help will be appreciated
*edit
SELECT count(*) AS `total`,
CASE c.state_id
WHEN 3 THEN 'active'
WHEN 5 THEN 'suspended'
ELSE 'inactive'
END AS `human_state`, `c`.*
FROM `code_statuses` AS `cs`
INNER JOIN `codes` AS `c`
ON c.code_id = cs.code_id
WHERE (cs.state_id=1 OR cs.state_id=2 OR cs.state_id=4)
GROUP BY `cs`.`code_id` HAVING (total<=4)
UNION
SELECT count(*) AS `total`,
CASE c.state_id
WHEN 3 THEN 'active'
WHEN 5 THEN 'suspended'
ELSE 'inactive'
END AS `human_state`, `c`.*
FROM `code_statuses` AS `cs`
INNER JOIN `codes` AS `c`
ON c.code_id = cs.code_id
WHERE (cs.state_id=5)
GROUP BY `cs`.`code_id`
HAVING (total<4)
The part before the union is $sq, the part afterwards is $sqtemp, the combination of the two gives the print out above
Both of them with union in is the whole thing
After a second look at your code, I suspect the oder() call on the union. You're ordering by cs.code_id, whic is not mentioned in any of the select statements, nor is the c.code_id for that matter.
Try adding either c.code_id or cs.code_id to the SELECT't that make up the UNION, possibly consider using an alias, which you can then use in your order clause.
$sq = $this->_codes->getAdapter()->select()
->from(array('cs' => 'code_statuses'),
array(
'total' => 'count(*)'
'cscodeids' => 'code_ids',
));
//...
$union = $this->_codes->getAdapter()
->select()
->union(array($sq,$sqtemp))
->order('cscodeids');
This, I believe, should work. I've taken inspiration from various places. Here are some of the links that lead up to my answer (can't find all of them ATM):
MySQL union and order by help
Every derived table must have its own alias - error from combination descending MySQL
Using union and order by clause in mysql
How to use union in zend db
Zend_Db union issue: old bug report... contains some details
This is my first question here. I searched a lot off docs, but can't find answer.
I have 3 tables.
product_main(with idx and name)<br />
proudct_attributes (with idx 'pid gid value)<br />
product_attributes_groups (with idx name) <br />
Now I trying to filter products by attributes. I have no problem with single attribute, but I can't make it work to filter with several conditions i.e. (red or blue , but only new)
SELECT `pid` FROM `product_attributes`
LEFT JOIN `product_main` ON `product_attributes`.`pid` = `product_main`.`idx`
LEFT JOIN `product_attributes_groups` ON `product_attributes`.`gid` = `product_attributes_groups`.`idx`
WHERE
(
(`product_attributes_groups`.`name` = 'color' AND `product_attributes`.`value` ='red' )
OR
(`product_attributes_groups`.`name` = 'color' AND `product_attributes`.`value` ='blue' )
)
AND
(`product_attributes_groups`.`name` = 'condition' AND `product_attributes`.`value` ='new' )
EDIT:
This helped:
select pm.idx
from product_attributes as pa join
product_main as pm
on pa.pid = pm.idx join
product_attributes_groups as pig
on pa.gid = pig.idx
group by pm.idx
having sum(pig.name = 'color' AND pa.value in ('red' , 'blue')) > 0 and
sum(pig.name = 'condition' AND pa.value ='used') > 0;
Answer by Gordon, with a little editing.
You have a "set-within-sets" query, where you are trying to find matches within a group (attributes on a product). I like to solve these with aggregation and a having clause:
select pm.pid
from product_attributes pa join
product_main pm
on pa.`pid` = pm.`idx` join
product_attributes_groups pig
on pm.`gid` = `pig`.`idx`
group by pm.pid
having sum(pig.`name` = 'color' AND `pa`.`value` in ('red' , 'blue')) > 0 and
sum(pig.`name` = 'condition' AND pa.`value` ='new') > 0;
Each condition in the having clause is counting the number of rows for each pid that match one condition.
A condition like
WHERE
`product_attributes_groups`.`name` = "something"
AND `product_attributes_groups`.`name` = "something else"
can never be true. Check what you're aiming to do and rewrite your filter.
Try this one. It should work with the combination (name AND (red OR blue)) OR (condition AND new)
SELECT `pid` FROM `product_attributes`
LEFT JOIN `product_main` ON `product_attributes`.`pid` = `product_main`.`idx`
LEFT JOIN `product_attributes_groups` ON `product_attributes`.`gid` = `product_attributes_groups`.`idx`
WHERE
(`product_attributes_groups`.`name` = 'color' AND (`product_attributes`.`value` ='red' OR `product_attributes`.`value` ='blue') )
OR
(`product_attributes_groups`.`name` = 'condition' AND `product_attributes`.`value` ='new' )
I am new to php. I can't figure out how to query my db to list this mockup. For each array, I want to query the db to list only what is related to the left in ''.
My db consist of 2 tables.
table1 = album
id, name
table2 = picture
id, album, picPath
$q_albums = array(
'People' => array(
ALBUM_PATH.'4.jpg',
ALBUM_PATH.'11.jpg',
ALBUM_PATH.'10.jpg'),
'Nature' => array(
ALBUM_PATH.'2.jpg',
ALBUM_PATH.'3.jpg',
ALBUM_PATH.'5.jpg',
ALBUM_PATH.'6.jpg',
ALBUM_PATH.'7.jpg'),
'Art' => array(
ALBUM_PATH.'1.jpg',
ALBUM_PATH.'8.jpg',
ALBUM_PATH.'9.jpg',
ALBUM_PATH.'2.jpg'),
'Wilderness' => array(
ALBUM_PATH.'3.jpg',
ALBUM_PATH.'2.jpg',
ALBUM_PATH.'5.jpg',
ALBUM_PATH.'7.jpg',
ALBUM_PATH.'6.jpg'),
'Photography' => array(
ALBUM_PATH.'8.jpg',
ALBUM_PATH.'1.jpg',
ALBUM_PATH.'9.jpg',
ALBUM_PATH.'12.jpg'),
'Fashion' => array(
ALBUM_PATH.'11.jpg',
ALBUM_PATH.'4.jpg',
ALBUM_PATH.'10.jpg'),
);
As dev-null-dweller notes, you need to build the array from the query results in a loop. Fortunately, it's pretty easy:
$sql = <<<END
SELECT album.name AS albumName, picture.picPath AS picPath
FROM album JOIN picture ON album.id = picture.album
END;
$res = $mysqli->query( $sql );
$q_albums = array();
while ( $row = $res->fetch_object() ) {
// this line actually build the array, entry by entry:
$q_albums[ $row->albumName ][] = $row->picPath;
}
$res->close();
Edit: As Mr. Radical notes, if you want your results to include empty albums, you should change the JOIN to a LEFT JOIN. If you do that, the query will return a row with a null picPath for any empty albums, so you'll have to deal with those null paths somehow. One way would be to include something like the following code after building the array:
foreach ( $q_albums as $album => &$pics ) {
// remove dummy null entries from empty albums
if ( !isset( $pics[0] ) ) array_shift( $pics );
}
#Ilmari Karonen I would use LEFT JOIN instead of JOIN.
SELECT album.name AS albumName, picture.picPath AS picPath
FROM album LEFT JOIN picture ON album.id = picture.album
table 1 = events -> holds a list of events
table 2 = response -> holds a list of users responses has a foreign key of eid which corresponds with events table
I need to join the tables together so it can return an array similar to this on php.
array(
0 => array(
'title' =>'', //title of events table
'contents' =>'this is a demo', //contents of events table
'users' => array( //users comes from response table
0 = array(
'firstname'=>'John',
),
1 = array(
'firstname'=>'James',
)
)
)
);
can this be done? using mysql only? coz i know you can do it on php.
You can gather all the necessary data in MySQL with a single JOIN query.
However, PHP will not return an array like your example by default. You would have to loop over the query result set and create such an array yourself.
I'm pretty sure the answer is no, since mysql always returns a "flat" resultset. So, you can get all the results you're looking for using:
SELECT e.title, e.contents, r.firstname
FROM events e LEFT JOIN response r ON e.id = r.eid
ORDER BY e.id, r.id
And then massaging it into the array with php, but I imagine this is what you're doing already.
EDIT:
By the way, if you want 1 row for each event, you could use GROUP_CONCAT:
SELECT e.title, e.contents, GROUP_CONCAT(DISTINCT r.firstname ORDER BY r.firstname SEPARATOR ',') as users
FROM events e LEFT JOIN response r ON e.id = r.eid
GROUP BY e.id
Just as Jason McCreary said. For you convenience, here is the query you need (though the field names might not be matching your db structure, as you did not provide this information)
SELECT
*
FROM
events
LEFT JOIN
responses ON (events.id = responses.eid)
The SQL is:
SELECT events.id, events.title, events.contents,
response.id AS rid, response.firstname
FROM events LEFT JOIN response
ON events.id = response.eid
I thought I would show you how to massage the results in to the array as you wished:
$query = "SELECT events.id, events.title, events.contents, response.id AS rid, response.firstname
FROM events LEFT JOIN response ON events.id = response.eid";
$result = mysql_query($query);
$events = array();
while ($record = mysql_fetch_assoc($result)) {
if (!array_key_exists($record['id'], $events)) {
$events[$record['id']] = array('title' => $record['title'], 'contents' => $record['contents'], 'users' => array());
}
if ($record['rid'] !== NULL) {
$events[$record['id']]['users'][$record['rid']] = array('firstname' => $record['firstname']);
}
}
mysql_free_result($result);