cakephp join from sorted and limited row - mysql

I have a working SQL query i want to figure out what would be the CakePHP query builder equivalent to work the exact same way?
SELECT customers.*, customer_reps.created FROM customers
LEFT JOIN customer_reps ON customer_reps.id =
(
SELECT id FROM customer_reps WHERE customer_id = customers.id
ORDER BY id ASC LIMIT 1
)
WHERE created >= 1475298000
AND created <= 1476217836
AND agents_id = 4
So essentially i am selecting all columns from "customers" and then i want only the "created" timestamp field of the FIRST "customer_reps" table for matching customer.
Documentation on CakePHP doesn't seem to explain how to do the select within select for sorting as this. I tried using the "hasMany" relational stuff but i was not able to find how to just get the "first" customer_reps entry to add to the main query for use in WHERE clause.
Thanks

try this code as a starting point you just need to group it by CustomerRep.customer_id because the order is already ascending if you're customer_reps table id is auto incremented already
$this->Customer->find('all', array(
'fields' => arrray(
'Customer.*',
'CustomerRep.created'
),
'joins' => array(
array(
'type' => 'LEFT',
'table' => 'customer_reps',
'alias' => 'CustomerRep',
'conditions' => 'Customer.id = CustomerRep.customer_id'
)
)
'conditions' => array(
'Customer.created >=' => '1475298000',
'Customer.created <=' => '1476217836',
'Customer.agentds_id' => 4
),
'group' => 'CustomerRep.customer_id'
));

Are you familiar with cakephp query builder? then if yes you should understand this flow
Step 1: SELECT customers.*, customer_reps.created FROM customers equivalent in cakephp is
$this->Customer->find('all', array(
'fields' => array(
'Customer.*',
'CustomerReply.created'
)
);
Note: CustomerReply.created is from join table of customer_reps which I just alias CustomerReply
Step 2: LEFT JOIN customer_reps ON customer_reps.id =
(
SELECT id FROM customer_reps WHERE customer_id = customers.id
ORDER BY id ASC LIMIT 1
) equivalent in cakephp is
'joins' => array(
array(
'table' => 'customer_reps',
'type' => 'left',
'alias' => 'CustomerReply',
'conditions' => array(
'CustomerReply.id = (SELECT id FROM customer_reps WHERE customer_id = Customer.id ORDER BY id ASC LIMIT 1)'
)
))
Step 3: WHERE created >= 1475298000
AND created <= 1476217836
AND agents_id = 4 equivalent in cakephp is
'conditions' => array(
'Customer.created >=' => 1475298000,
'Customer.created <=' => 1476217836,
'Customer.agents_id' => 4
)
);
so your cakephp query builder would be like this
$query = $this->Customer->find('all', array(
'fields' => array(
'Customer.*',
'CustomerReply.created'
),
'joins' => array(
array(
'table' => 'customer_reps',
'type' => 'left',
'alias' => 'CustomerReply',
'conditions' => array(
'CustomerReply.id = (SELECT id FROM customer_reps WHERE customer_id = Customer.id ORDER BY id ASC LIMIT 1)'
)
)),
'conditions' => array(
'Customer.created >=' => 1475298000,
'Customer.created <=' => 1476217836,
'Customer.agents_id' => 4
)
));

Related

how to combine 2 sql queries to get 1 result

SELECT users.name, users.registrationdate, users.city, users.status
FROM users, referrals
WHERE users.username= referrals.referrals AND referrals.username='user_name'
SELECT adearning, reffearning
FROM earnings WHERE usersname='user_name33'
How can I combine these two queries as if first query condition doesn't match and doesn't run.. then the second query should run and return some value if condition match
Try this
$query1 = $this->db->query("SELECT users.name, users.registrationdate, users.city, users.status
FROM users, referrals
WHERE users.username = referrals.referrals AND referrals.username='user_name'")
$result1 = $query1->result_array();
$query2 = $this->db->query("SELECT adearning, reffearning FROM earnings WHERE usersname='user_name33' ")
$result2 = $query2->result_array();
$dataArray = array_merge($result1, $result2);
if want to check the result, end of the line add this
print_r($dataArray);die;
On this it will print all of them in one array
Example
$result1 = array(
'0' => 'sjhccsd',
'1' => 'ddd',
'2' => 'df',
'3' => 'dfd',
);
$result2 = array(
'0' => 'sjhccsd',
'1' => 'ddd',
'2' => 'df',
'3' => 'dfd',
);
$dataArray = array_merge($result1, $result2);
print_r($dataArray);
Output : Array ( [0] => sjhccsd [1] => ddd [2] => df [3] => dfd [4] => sjhccsd [5] => ddd [6] => df [7] => dfd )

Wordpress meta_query not working

I want to all records from my postmeta table where meta_key = 'teljesitmeny' and meta_value between 0 and 150.
I make this query, but it's not working:
$argsg = array(
'post_type' => 'termek',
'meta_query' => array(
array(
'key' => 'teljesitmeny',
'value' => array(0, 150),
'compare' => 'BETWEEN'
),
),
);
$scheduled = '';
$scheduled = new WP_Query( $argsg );
It's only post one query, where meta_value is 150.
Datas in postmeta table:
Datas after execute the query:
What did i wrong?
Update:
I found the solution:
SELECT *
FROM `eopwrqjnc_postmeta`
WHERE `meta_key` LIKE 'teljesitmeny'
AND `meta_value`
BETWEEN CAST( 0 AS UNSIGNED )
AND CAST( 150 AS UNSIGNED )
LIMIT 0 , 30

Optimizing an union SQL query

I've got a big query that all contain same types I need for a feed that I list in my app. Now the problem is that this query isn't very fast. I'm thinking that if I limit each individual union it might speed it up a bit but I'm not sure.
So basically my question is how could I optimize this query to execute faster?
SELECT DISTINCT
alert_id,
uniquekey,
type,
user_id,
date_added
FROM
(
( SELECT
r.alert_id,
r.alert_id AS uniquekey,
'reply' AS `type`,
r.user_id,
r.date_added
FROM
`reply` r
LEFT JOIN `alerts` a
ON r.alert_id = a.alert_content_id
WHERE
r.user_id = :id
AND a.hide = '0'
ORDER BY
date_added DESC )
UNION
( SELECT
r.alert_id,
r.alert_id AS uniquekey,
'replyfromfollowing' AS `type`,
r.user_id,
r.date_added
FROM
`reply` r
LEFT JOIN `alerts` a
ON r.alert_id = a.alert_content_id
WHERE
r.user_id IN( '$followingstring' )
AND a.hide = '0'
ORDER BY date_added DESC )
UNION
( SELECT
i.alert_id,
i.alert_id AS uniquekey,
'liked' AS `type`,
i.user_id,
i.date_added
FROM
`interactions` i
LEFT JOIN `alerts` a
ON i.alert_id = a.alert_content_id
WHERE
i.user_id = :id
AND a.hide = '0'
GROUP BY
alert_id
ORDER BY
date_added DESC )
UNION
( SELECT
i.alert_id,
i.alert_id AS uniquekey,
'likedfromfollowing' AS `type`,
i.user_id,
i.date_added
FROM
`interactions` i
LEFT JOIN `alerts` a
ON i.alert_id = a.alert_content_id
WHERE
i.user_id IN ( '$followingstring' )
AND a.hide = '0'
GROUP BY
alert_id
ORDER BY
date_added DESC )
UNION
( SELECT
alerts as alert_id,
alert_content_id AS uniquekey,
'following' AS `type`,
user_id,
date_added
FROM
alerts a
LEFT JOIN `alerts_content` ac
ON ac.id = a.alert_content_id
WHERE
a.user_id IN ( '$followingstring' )
AND ac.anoniem = '0'
AND a.hide = '0'
GROUP BY
alert_id
ORDER BY
date_added DESC )
) joined
GROUP BY
uniquekey
ORDER BY
date_added DESC
LIMIT
".(int)$start.",20"
table structures
Reply table Structure:
id
user_id
alert_id
description
reply_on_alert
reply_on_reply
date_added
Interaction table Structure:
id
alert_id
action_id
reply_id
user_id
date_added
Alerts table structure(Yes i know BIG mistake naming `id` : `alerts`):
alerts
title
alert_content_id
user_id
cat
lat
lon
state
hide
date_added
alerts_content table structure:
id
alert_id
description
img
results of query:
Array
(
[0] => Array
(
[alert_id] => 173404
[uniquekey] => 173404
[type] => reply
[user_id] => 2
[date_added] => 2015-06-01 16:34:16
)
[1] => Array
(
[alert_id] => 172174
[uniquekey] => 172174
[type] => replyfromfollowing
[user_id] => 1380
[date_added] => 2015-06-01 16:01:04
)
[2] => Array
(
[alert_id] => 171772
[uniquekey] => 171772
[type] => liked
[user_id] => 2
[date_added] => 2015-06-01 15:58:44
)
[3] => Array
(
[alert_id] => 149423
[uniquekey] => 149423
[type] => reply
[user_id] => 2
[date_added] => 2015-06-01 15:25:56
)
[4] => Array
(
[alert_id] => 164742
[uniquekey] => 164742
[type] => reply
[user_id] => 2
[date_added] => 2015-05-12 09:46:39
)
[5] => Array
(
[alert_id] => 163344
[uniquekey] => 163344
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-05-12 09:44:46
)
[6] => Array
(
[alert_id] => 164205
[uniquekey] => 164205
[type] => liked
[user_id] => 2
[date_added] => 2015-05-11 11:06:39
)
[7] => Array
(
[alert_id] => 160890
[uniquekey] => 160890
[type] => replyfromfollowing
[user_id] => 1380
[date_added] => 2015-05-08 14:29:34
)
[8] => Array
(
[alert_id] => 163002
[uniquekey] => 163002
[type] => replyfromfollowing
[user_id] => 1380
[date_added] => 2015-05-08 13:31:12
)
[9] => Array
(
[alert_id] => 159123
[uniquekey] => 159123
[type] => replyfromfollowing
[user_id] => 48
[date_added] => 2015-04-30 15:10:32
)
[10] => Array
(
[alert_id] => 150546
[uniquekey] => 150546
[type] => replyfromfollowing
[user_id] => 16
[date_added] => 2015-04-21 21:52:49
)
[11] => Array
(
[alert_id] => 149497
[uniquekey] => 149497
[type] => reply
[user_id] => 2
[date_added] => 2015-04-10 15:19:06
)
[12] => Array
(
[alert_id] => 141078
[uniquekey] => 141078
[type] => liked
[user_id] => 2
[date_added] => 2015-04-10 15:15:32
)
[13] => Array
(
[alert_id] => 125466
[uniquekey] => 125466
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:15:22
)
[14] => Array
(
[alert_id] => 134592
[uniquekey] => 134592
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:11:04
)
[15] => Array
(
[alert_id] => 124194
[uniquekey] => 124194
[type] => likedfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:08:35
)
[16] => Array
(
[alert_id] => 128645
[uniquekey] => 128645
[type] => likedfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:07:29
)
[17] => Array
(
[alert_id] => 144867
[uniquekey] => 144867
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-04-06 13:59:19
)
[18] => Array
(
[alert_id] => 133355
[uniquekey] => 133355
[type] => liked
[user_id] => 2
[date_added] => 2015-03-31 16:16:15
)
[19] => Array
(
[alert_id] => 141075
[uniquekey] => 141075
[type] => liked
[user_id] => 2
[date_added] => 2015-03-30 15:17:01
)
)
Some possibilities, in no particular order:
Optimization #1:
Use LIMIT in the subqueries, too. However, since you are using OFFSET, it may not be obvious how to do it.
Before the query, calculate $start+20 and put it into, say, $limit. Then use LIMIT $limit for the inner queries. No, don't use an OFFSET on them. This guarantees that you get enough rows from each query to satisfy the outer OFFSET $start LIMIT 20.
Optimization #2:
Restructure the tables so that you don't need to JOIN to another table (alerts) to find out whether to show the record. That is, having hide prevents a number of potential optimizations. Before advising further, we need to understand the need for LEFT. Are there rows in reply, etc, that are not in alerts? If not, get rid of the LEFT and look into searching alerts with theOFFSETandLIMIT`, then joining to the 4 other tables.
Optimization #3:
Restructure the data so that there is one core table, with alerts and the 4 other tables hanging off it. Be sure to have most (all?) of the fields needed for this query in this new table.
Optimization #4:
The current structure requires the full scan of each of the 4 tables before even thinking about OFFSET and LIMIT. This smells like "pagination"; is it? For optimizing "pagination", the goals are to avoid the table scan and OFFSET; instead remember where you "left off" so that the query can be
WHERE ... AND x < $left_off
ORDER by x DESC
LIMIT 20
This should make it possible to read only 20 rows, not the entire table(s). That would make the query much faster, especially for later pages. (A bigger OFFSET costs more time`)
I discuss pagination optimization in my blog.

Altering a query to consolidate answers in a poll

I have the following mysql query:
SELECT p.id, p.title, p.description, a.id, a.answer, q.id, q.question
FROM x_trybe_poll_relation pr
LEFT JOIN x_polls p
ON pr.poll_id = p.id
LEFT JOIN x_polls_question_relation qr
ON p.id = qr.poll_id
LEFT JOIN x_polls_questions q
ON qr.question_id = q.id
LEFT JOIN x_polls_answers a
ON q.id = a.question_id
WHERE pr.trybe_id = '%s'
Which returns:
[polls] => Array
(
[0] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answer] => Danny Welbeck
[question] => Who is the best player in the Arsenal squad?
)
[1] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answer] => Alexis Sanchez
[question] => Who is the best player in the Arsenal squad?
)
)
How do I adjust the mysql query to get the following:
[polls] => Array
(
[0] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answers] => Array (
[0] => Array (
[id] => abc
[answer] => Danny Welbeck
)
[1] => Array (
[id] => def
[answer] => Alexis Sanchez
)
)
[question] => Who is the best player in the Arsenal squad?
)
)
I want to get the poll question, and get the array of pre-generated answers with one query.
Is this possible, or should I just run two queries?
Thanks

LEFT JOIN (mysql)

How to left joing?
Left table
SELECT TYPE , days
FROM leavetypes
type days
anual 10
casual 6
sick 10
right table
SELECT sub_leave_type, (
SUM( working_days )
) AS used
FROM vacations
WHERE `user_id` = '1'
AND `from_date`
BETWEEN '2012-01-01'
AND '2012-12-31'
GROUP BY sub_leave_type
sub_leave_type used
anual 3
casual 6
actually I am doing this on cakephp this is my code.
$allleaves = $this->Leavetype->find('all', array(
'joins' => array(
array(
'table' => 'vacations',
'alias' => 'vacationsJoin',
'type' => 'left',
'conditions' => array('vacationsJoin.sub_leave_type = Leavetype.type')
)
),
'conditions' => array(
'vacationsJoin.user_id' => $_SESSION['Auth']['User']['id'],
'vacationsJoin.from_date BETWEEN ? and ?' => array(date('Y') . '-01-01',
date('Y') . '-12-31')
),
'fields' => array('type', 'days', '(SUM(working_days)) as used'),
'group' => 'sub_leave_type',
));
$this->set(compact('allleaves'));
This not out out that what i want, I want is all the row of left table and others from vacations table
Please read this query and change it according to your requirement
SELECT column_name(s)
FROM table_name1
LEFT JOIN table_name2
ON table_name1.column_name=table_name2.column_name
I was correct the problem here is the answer. main problem was in GROUP
$allleaves = $this->Leavetype->find('all', array(
'joins' => array(
array(
'table' => 'vacations',
'alias' => 'vacationsJoin',
'type' => 'left',
'conditions' => array('vacationsJoin.sub_leave_type = Leavetype.type',
'vacationsJoin.user_id' => $_SESSION['Auth']['User']['id'],
'vacationsJoin.from_date BETWEEN ? and ?' => array(date('Y') . '-01-01',
date('Y') . '-12-31'),'vacationsJoin.status'=>'approved'
)
)
),
'fields' => array('type', 'days', '(SUM(working_days)) as used'),
'group' => 'type'
));
$this->set(compact('allleaves'));