I have bellow raw mysql query, what i want to do is to change this to query builder. need help.
SET #groupIds = '11,14';
SET #eventIds = '13,5';
SET #friendIds = '1000022';
SET #userFollowings = '1000001';
$query = "SELECT sn_posts.*
FROM sn_posts
WHERE
sn_posts.deleted_at is null AND
(
sn_posts.user_id = '1000042' OR (
(
IF(#groupIds is not null AND #groupIds <> '',FIND_IN_SET(sn_posts.postable_id,#groupIds),0)
OR IF(#eventIds is not null AND #eventIds <> '',FIND_IN_SET(sn_posts.postable_id,#eventIds),0)
OR IF(sn_posts.privacy_level = 0, (
IF(#friendIds is not null AND #friendIds <> '', FIND_IN_SET(sn_posts.`user_id`,#friendIds),0)
OR IF(#userFollowings is not null AND #userFollowings <> '',FIND_IN_SET(sn_posts.`user_id`,#userFollowings),0)
),
IF(#friendIds is not null AND #friendIds <> '', FIND_IN_SET(sn_posts.user_id,#friendIds),0)
)
)
AND IF(sn_posts.`parent_id` IS NOT NULL,(
SELECT parent.id FROM sn_posts AS parent
WHERE parent.id = sn_posts.`parent_id` AND IF(parent.privacy_level = 0,1,IF(#friendIds is not null AND #friendIds <> '', FIND_IN_SET(parent.`user_id`,#friendIds),0))
),1)
)
)
ORDER BY sn_posts.created_at desc
LIMIT 21,10";
$result = DB::raw(DB::select($query));
I have php variables instead of those mysql variables.
Because of need for result as collection, i need a way to get the result as collection.
What I have tried:
$result = Post::where('deleted_at', null)
->where(function($query) use($authUserID,$friendIds,$userFollowings,$groupIds,$eventIds) {
$query->where('user_id', $authUserID);
orWhere(function($query) use($friendIds,$userFollowings,$groupIds,$eventIds) {
$query->whereIn('postable_id', $groupIds)
->orWhereIn('postable_id', $eventIds)
->orWhere(function($query) use ($friendIds, $userFollowings) {
if ($query->where('privacy_level', 0)) {
$query->whereIn('user_id', $friendIds)
->orWhereIn('user_id', $userFollowings);
} else {
$query->whereIn('user_id', $friendIds);
}
});
})->where(function($query) use($friendIds){
***if ($query->whereNotNull('parent_id')) {
DB::raw('select parent.id from sn_posts as parent where parent.id = '.$query->parent_id.'
and if(parent.privacy_level = 0,1,
if('.$friendIds.' is not null and '.$friendIds.' <> "", FIND_IN_SET(parent.user_id, '.$friendIds.'), 0))
}***
});
});
The main problem is on checking access level of parent post (between stars blocks) of current shared post. It means i want to check if current post is a shared post, then check if it is parent is a public post, or it is a post from my friends, then get that shared post, else escape.
Related
Can anyone please help me get the count of the filled MySQL columns?
For example:
My Table Structure:
ID
FName
LName
1
ABC
NULL
2
XYZ
In the above table, I have two Rows, and both rows contain one Null and One Empty Value, I just need to get the Count of each row that doesn't have NULL OR EMPTY Value for a specific ID.
Expected Result:
WHERE ID=1, the result would be:
Count = 2 (ID, FName)
WHERE ID=2, the result would be:
Count = 2 (ID, LName)
**I want to use this in WordPress
So, after searching for an hour or two.
I'm using this as my solution but I'm not sure if it's good regrading the optimization. Here is what I'm using:
function ranking_mechanism( $currentUserID ){
global $wpdb;
$rank = 0;
$results = $wpdb->get_row(
$wpdb->prepare('SELECT * FROM TABLE WHERE ID=%d', $currentUserID)
);
$finalArr = (array) $results; // Convert $results as Array(to perform iteration), it(WordPress DB Query) typically return Object by Default
foreach ( $finalArr as $key => $Table ) {
if( $finalArr[$key] == '' || $finalArr[$key] == 'NULL' ){
// Nothing to do
}else{
$rank = $rank+1; // Increase Rank If Found Value
}
return $rank;
}
SELECT ID, (ID IS NOT NULL) /* assuming that ID is numeric and cannot be empty string */
+ (FName <> '' AND FName IS NOT NULL)
+ (LName <> '' AND LName IS NOT NULL) AS `Count`
FROM source_table
-- WHERE ID = ???
This question already has answers here:
How to create a MySQL hierarchical recursive query?
(16 answers)
Closed 4 years ago.
I have a MYSQL table called collections when viewed and implemented as a table could be something like this:
I needed to know whether one mysql query will be able to get all the products under a collection type entry (a given) which could have collections under it. For example, if I select 10, it should return 14, 12, 13, and 15.
I implemented a solution that involves a do..while loop...
$concatted = 10;
$products = [];
do {
$sql = "SELECT id, type FROM collections WHERE parent IN ($id_concatted)";
$result = $mysqli->query($sql);
if($result) {
while($row = $result->fetch_object()){
if($row->type == 'product') {
apply_changes_to_product($row->id);
} elseif ($row->type=='collection'){
$collections[] = $row->id;
}
}
}
if(count($collections) > 0){
$id_concatted = implode($collections, ",");
$continue = true;
$collections = [];
} else {
$continue = false;
}
} while ($continue);
I think that the above code is not efficient. I think it is doable with one query but I don't know how.
UPDATE: I mark this as a duplicate of How to create a MySQL hierarchical recursive query although in that post there is NO accepted solution. I got myself this solution based on one reply there (Mysql 5.6):
SELECT id, `type` FROM (
select id, `type`
from (select * from collections
order by parent, id) products_sorted,
(select #pv := '10') initialisation
where find_in_set(parent, #pv)
and length(#pv := concat(#pv, ',', id))
) products
WHERE
products.`type` = 'product'
The fiddle is http://sqlfiddle.com/#!9/ea214f/2.
yes, you may need to use subquery and first fetch id where parent = selectedId and type = 'collection' and then select id where parent in the subquery id and type = 'product'
Like below:
SELECT id, type FROM collections WHERE parent IN (select id from collections where
parent = $id_concatted and type = 'collection') and type = 'product'
For Multiple level, Use Recursive feature of MySql. Like below:
WITH RECURSIVE COLLECTIONS_PRODUCTS (ID, TYPE, PATH)
AS
(
SELECT ID, TYPE, CAST(ID AS CHAR(200))
FROM COLLECTIONS
WHERE PARENT IN ($id_concatted)
UNION ALL
SELECT S.ID, S.TYPE, CONCAT(M.PATH, ",", S.ID)
FROM COLLECTIONS_PRODUCTS M JOIN COLLECTIONS S ON M.ID=S.PARENT
)
SELECT * FROM COLLECTIONS_PRODUCTS WHERE TYPE = 'product' ORDER BY PATH;
I am wanting to count the null columns or with a certain value
$q = mysql_query("
SELECT SUM(
(`foto` = 'avatar_small.png') +
(`email` IS NULL) +
(`cidade` IS NULL) +
(`estado` IS NULL) +
(`endereco` IS NULL) +
(`numero` IS NULL) +
(`cep` IS NULL) +
(`telefone` IS NULL)
) FROM `info_complementos` WHERE id_user = ".$_SESSION['usuario_cargo']) or die(mysql_error());
$retorno = mysql_num_rows($q);
return $retorno[0];
the problem is that it shows the result
You can use the COUNT function in mysql to count the rows returned. So you want to filter out the rows that you do not want in the WHERE clause. This will count all the rows that match ALL the conditions. You can change the AND to OR if you want to match rows that contain some NULL values.
<?php
$q = mysql_query("
SELECT COUNT(*) FROM `info_complementos`
WHERE
id_user = $_SESSION['usuario_cargo'] AND
`foto` = 'avatar_small.png' AND
`email` IS NULL AND
`cidade` IS NULL) AND
`estado` IS NULL) AND
`endereco` IS NULL AND
`numero` IS NULL AND
`cep` IS NULL AND
`telefone` IS NULL");
$result = mysql_fetch_array($q);
echo $result[0];
Hope this helps.
I have a problem, it may be a simple fix to the issue, but I can't seem to figure it out. I am new to PHP and MySQL, so I'm reading everything everywhere, but lack of experience is very frustrating, as often times it takes ages to realize a small error. Please look at the following tables and read below the questions.
The PHP/mysql is in Joomla environment, I am trying to modify a plugin, so that is updates with values from different tables into a set of other tables, that were not originally intended, but all tables reside in the same database.
Table 1 vm_orders
---------------------------------------------
order_id user_id
---------------------------------------------
20 1
55 6
65 2
30 4
50 67
Table 2 vm_order_item
---------------------------------------------
order_item_id order_id order_item_sku
---------------------------------------------
20 20 1
55 55 35
65 65 60
30 30 22
50 50 3
Table 3 xipt_ users
---------------------------------------------------
userid Profiletype template
----------------------------------------------------
1 1 default
6 3 default
2 1 default
4 8 default
67 7 default
Table 4 community_fields_values
---------------------------------------------
id user_id field_id value
---------------------------------------------
1 1 55 Female
2 6 35 Cat
3 2 2 2
4 4 18 Texas
5 67 12 bike
What I need to is first of all get the order number according to the user that has place the order.
The userid variable is being passed from elsewhere in the script. That part is working fine.
So the user 67 has placed an order. These are the things I want to achieve.
Query 1: I want to get the "orderid" value from "order_id" column of vm_orders table (table 1); i will call the result "vmorderid" and use it in another query.
Query 2: Using the "vmorderid" from query 1 as the order_id value in the "order_id" column of vm_order_item table (table 2).
I want to get the order_item_sku value from the "order_item_sku" column of my_order_item table (table 2).
I will call the result "vmsku" and use it in another query.
Query 3: Using the "vmsku" from query 2 as the profiletype value in the "Profiletype" column of vm_users table (table 3).
I want to UPDATE the value of the "profiletype" column, with "vmsku" value.
Query 4: Using the "vmsku" from query 2 as the value in the "value" column of community_fields_values (table 4).
I want to UPDATE the value of the "value" column in my_fields_values (table 4) "vmsku" value.
Okay, I hope you are with me so far, I have tried a couple of queries, but it's not working.
Here is what I have so far:
Assuming the user it is being passed from a param field.
$userid = $this->params->get('userid', 'defaultValue');
function _vm_custom_order($vmorderId)
{
$vmorderId = $database->loadResult();
$database = JFactory::getDBO();
// query the db to see if the user is already a member of group
$vmorderId ="
SELECT MAX
`order_id`
FROM
#__vm_orders';
WHERE
`user_id` = '{$userid}'
";
$database->setQuery( $vmorderId );
$data = $database->loadResult();
return $data;
}
function _vm_sku($vmsku)
{
$vmsku = $database->loadResult();
$database = JFactory::getDBO();
// query the db to see if the user is already a member of group
$vmsku = "
SELECT
`product_sku`
FROM
#__vm_order_item';
WHERE
`order_id` = '{$vmorderId}'
";
$database->setQuery( $vmsku );
$data = $database->loadResult();
return $data;
}
function _add( $userid, $groupid, $vmsku)
{
$success = false;
$database = JFactory::getDBO();
if (!$allow_multiplegroups = $this->params->get( 'allow_multiplegroups', '1' )) {
// query the db to see if the user is already a member of ANY group
$database->setQuery("
SELECT
`profiletype`
FROM
#__xipt_users
WHERE
`userid` = '{$userid}'
");
$member = $database->loadResult();
// if so, do not execute
if (intval($member) > 0) {
return $success;
}
}
$already = plgAmbrasubsAddToXipt::_already( $userid, $groupid );
if (($already != $userid))
{
$database->setQuery("
SELECT MAX
`order_id`
FROM
#__vm_orders
WHERE
`user_id` = '{$userid}'
");
$vmorderId = $database->loadResult();
if ($database->query()) {
$success = true;
}
}
if (($already != $userid))
{
$database->setQuery("
SELECT
`product_sku`
FROM
#__vm_order_item
WHERE
`order_id` = '{$vmorderId}'
");
$vmsku = $database->loadResult();
if ($database->query()) {
$success = true;
}
}
// if they aren't already a member of the group, add them to the group
if (($already != $userid))
{
$database->setQuery("
UPDATE
#__xipt_users
SET
`profiletype` = '{$vmsku}'
WHERE
`userid` = '{$userid}'
LIMIT 1
");
if ($database->query()) {
$success = true;
}
}
return $success;
}
}
I also tried it this way:
function _add( $userid, $groupid, $vmsku)
{
$success = false;
$database = JFactory::getDBO();
if (!$allow_multiplegroups = $this->params->get( 'allow_multiplegroups', '1' )) {
// query the db to see if the user is already a member of ANY group
$database->setQuery("
SELECT
`profiletype`
FROM
#__xipt_users
WHERE
`userid` = '{$userid}'
");
$member = $database->loadResult();
// if so, do not execute
if (intval($member) > 0) {
return $success;
}
}
$already = plgAmbrasubsAddToXipt::_already( $userid, $groupid );
if (($already != $userid))
{
$database->setQuery("
SELECT MAX
`order_id`
FROM
#__vm_orders
WHERE
`user_id` = '{$userid}'
");
$vmorderId = $database->loadResult();
if ($database->query()) {
$success = true;
}
}
if (($already != $userid))
{
$database->setQuery("
SELECT
`product_sku`
FROM
#__vm_order_item
WHERE
`order_id` = '{$vmorderId}'
");
$vmsku = $database->loadResult();
if ($database->query()) {
$success = true;
}
}
// if they aren't already a member of the group, add them to the group
if (($already != $userid))
{
$database->setQuery("
UPDATE
#__xipt_users
SET
`profiletype` = '{$vmsku}'
WHERE
`userid` = '{$userid}'
LIMIT 1
");
if ($database->query()) {
$success = true;
}
}
return $success;
}
}
EDIT: I have now tried as suggested, to use JOIN to accomplish the task, so far no joy!
UPDATE
#__xipt_users
SET
`profiletype.#__xipt_users` = `product_sku.#__vmsku`
WHERE
`userid` = '{$userid}'
AND
(
SELECT `order_id.#__vm_orders`
FROM #__vm_orders, #__vm_order_item
LEFT JOIN #__vm_orders
ON #__vm_orders.`order_id` = #__vm_order_item.`order_id`
ORDER BY `order_id.#__vm_order` DESC LIMIT 1
WHERE
`user_id.#__vm_orders` = '{$userid}'
) AS #__vmorder_id
SELECT ` product_sku.#__vm_order_item`
FROM #__vm_order_item, #__vmorder_id
LEFT JOIN #__vm_order_item
ON `#__vm_order_item.order_id` = `#__vmorder_id.order_id`
WHERE
`order_id.#__vm_order_item` = `order_id.#__vmorder_id`
)
AS #__vmsku
LIMIT 1
");
Join Statements
I would suggest you start learning how to create Join Statements in MySQL.
Have a look at this website:
http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php
That way you are able to combine multiple queries into one. It will make this job a lot easier!
Piece of paper
Also it will help you to draw your database on a piece of paper to get a better overview of what you want to do. For example you can draw lines between the table fields you want to link.
I have an app that uses the codeigniter CXTags tagging library.
The database structure is as follows:
posts
id
tags_ref
row_id
table
tag_id
tags
id
safe_tag
tag
My query basically goes if $safe_tag is not null then join tags_ref on post.id = tags_ref.row_id, join tags on tags_ref.tag_id = tags.id, where tags_ref.table = 'posts' and tags.safe_tag = 'food'
SELECT * FROM posts
JOIN tags_ref ON posts.id = tags_ref.row_id
JOIN tags ON tags_ref.tag_id = tags.id
WHERE tags.safe_tag = $safe_id
Unfortunately the query I've written in active record is not functioning properly. The query works perfectly when £safe_tag is null but when it's not I get wrong results.
function get_posts($id = NULL, $safe_tag = NULL) {
if($safe_tag != NULL){
echo $safe_tag;//debugging
$table = 'posts';
$this->db->join('tags_ref', 'posts.id = tags_ref.row_id');
$this->db->join('tags', 'tags_ref.tag_id = tags.id');
$this->db->where('tags_ref.table', $table);
$this->db->where('tags.safe_tag',$safe_tag);
}
//if an id was supplied
if ( $id != NULL ) {
$this->db->where('posts.city_id',$id);
}
// execute query
$query = $this->db->get('posts');
...
Here is the query with profiling on:
SELECT *
FROM (`posts`)
INNER JOIN `tags_ref` ON `posts`.`id` = `tags_ref`.`row_id`
INNER JOIN `tags` ON `tags_ref`.`tag_id` = `tags`.`id`
WHERE `tags_ref`.`table` = 'posts'
AND `tags`.`safe_tag` = 'food'
AND `posts`.`city_id` = '2'
Can someone have a look? I think I need a fresh set of eyes on it.
Your forgot to actually run the query inside your first if{}
if($safe_tag != NULL){
echo $safe_tag;//debugging
$table = 'posts';
$this->db->join('tags_ref', 'posts.id = tags_ref.row_id');
$this->db->join('tags', 'tags_ref.tag_id = tags.id');
$this->db->where('tags_ref.table', $table);
$this->db->where('tags.safe_tag',$safe_tag);
$this->db->get(); // here
}