I have a table which, saves the subscriptions of users and guests to topic_names.
Here's the example, now I need to support a bunch of complex queries for example, get all the users who are subscribed to 'so' and 'all' or are subscribed to 'so2' in short : so && (all || so2) I first tried doing it via having clause, but looks like the same column doesn't work in that case, so I came up with this:
select *
from `wp_push_notification_topics`
where exists(select *
from `wp_push_notification_topics` as `wp_laravel_reserved_0`
where `wp_push_notification_topics`.`user_id` = `wp_laravel_reserved_0`.`user_id`
and `topic_name` = 'so'
and exists(select *
from `wp_push_notification_topics`
where `wp_laravel_reserved_0`.`user_id` = `wp_push_notification_topics`.`user_id`
and `topic_name` = 'all'
or exists(select *
from `wp_push_notification_topics` as `wp_laravel_reserved_1`
where `wp_push_notification_topics`.`user_id` = `wp_laravel_reserved_1`.`user_id`
and `topic_name` = 'so2')))
Which works fine.
But even if I change:
and `topic_name` = 'all'
to
and `topic_name` = 'all22'
I get this result:
Which is clearly the exact as the previous result and therefore wrong! user_id 2 row's must not be included, which means I'm doing something wrong, please help.
You can get the user_ids with aggregation if you set correctly the conditions in the HAVING clause:
SELECT user_id
FROM wp_push_notification_topics
GROUP BY user_id
HAVING SUM(topic_name = 'so') > 0 AND SUM(topic_name IN ('all', 'so2')) > 0;
If you want to restrict the conditions so that the user is not subscribed to any other than 'so', 'all' and 'so2' you can add to the HAVING clause:
AND SUM(topic_name NOT IN ('so', 'all', 'so2')) = 0
If you want all the rows of the table:
SELECT *
FROM wp_push_notification_topics
WHERE user_id IN (
SELECT user_id
FROM wp_push_notification_topics
GROUP BY user_id
HAVING SUM(topic_name = 'so') > 0 AND SUM(topic_name IN ('all', 'so2')) > 0
);
Related
I would like to get lowest price of product based on last crawled dates by various resellers. My current function is very basic, it gets me lowest price from table without considering reseller ids and crawled timestamps.
I've rough idea that we can SELECT * FROM "custom_data_table" and process the data using php. Please have a look at attachment for further clarification.
function get_lowest_price($table_id) {
global $wpdb;
$table_prices = $wpdb->get_results(
$wpdb->prepare(
"SELECT price FROM `custom_data_table` WHERE tableid= %d"
,$table_id)
);
if (!empty($table_prices) && $table_prices !== NULL)
return rtrim(min($table_prices)->price, '00');
}
The right query here is:
SELECT price
FROM custom_data_name cdn, (
SELECT MAX(crawled) AS maxCrawled, resellerid
FROM custom_data_name
GROUP BY resellerid
) cdnFiltered
WHERE cdn.crawled = cdnFiltered.maxCrawled AND
cdn.resellerid = cdnFiltered.resellerid AND
tableid = %d;
Try this:
SELECT B.price
FROM (SELECT resellerid, MAX(crawled) max_crawled
FROM custom_data_table
GROUP BY resellerid) A
JOIN custom_data_table B
ON A.resellerid=B.resellerid AND A.max_crawled=B.crawled;
Maybe use ORDER BY crawled and LIMIT 1
I have a table with 3 columns( name, objectroot_dn, distinguishedname). Here distinguishedname is like a parent to objectroot_dn. I have to find whether for each objectroot_dn is there a child exists or not?
I can do this using the query below. It will return True if there is a child, False if there is not. But my problem is when the total dataset gets increased it takes lots of time.
For example, If the total number of row is 50,000 then it takes 10 mins for this query to complete.
Since I'm using a framework for different database, I can't index the columns.
SELECT
name,
objectroot_dn,
distinguishedname,
CASE
WHEN (SELECT count(*)
FROM (SELECT name
FROM elaoucontainergeneraldetails
WHERE objectroot_dn = dn.distinguishedname
LIMIT 1) AS tabel1) > 0
THEN 'True'
ELSE 'False'
END
FROM elaoucontainergeneraldetails AS dn
WHERE objectroot_dn = 'SOME_VALUE';
Please let me know how can I increase the speed of this query.
Thanks in advance. Appreciate all help.
You can have the same solution using left join or exists:
SELECT
dn.name,
dn.objectroot_dn,
dn.distinguishedname,
CASE
WHEN dn_in.objectroot_dn is not null
THEN 'True'
ELSE 'False'
END
FROM elaoucontainergeneraldetails AS dn
LEFT JOIN elaoucontainergeneraldetails dn_in on dn_in.objectroot_dn = dn.distinguishedname
WHERE objectroot_dn = 'SOME_VALUE';
EXISTS(subquery) yields a boolean value:
SELECT dn.name
, dn.objectroot_dn
, dn.distinguishedname
, EXISTS (SELECT *
FROM elaoucontainergeneraldetails nx
WHERE nx.objectroot_dn = dn.distinguishedname
) AS truth_value
FROM elaoucontainergeneraldetails AS dn
WHERE dn.objectroot_dn = 'SOME_VALUE'
;
I'm having trouble constrsucting a query and getting it to run on impala. I created the following working query to join two tables:
SELECT *
FROM illuminavariant as vcf, ensembl_genes as ens
WHERE vcf.filter = "PASS"
AND vcf.qual > 100
AND vcf.chromosome = ens.chromosome
AND vcf.position BETWEEN ens.start AND ens.stop
Now I'm trying to write a query that finds all variants WHERE vcf.filter = "PASS" and vcf.qual > 100, but do not have a match by chromosome and position.
I've tried this:
SELECT *
FROM p7dev.illumina_test, p7dev.ensembl_test
WHERE NOT EXISTS(
SELECT *
FROM p7dev.illumina_test as vcf, p7dev.ensembl_test as ens
WHERE vcf.chromosome = ens.chromosome
AND vcf.position BETWEEN ens.start AND ens.stop
)
But that's not returning any results. I think a WITH clause might do the trick, but I'd really appreciate if anybody could help me wrap my head around the logic of how that would work. Thanks so much!
Since you're looking for variants that are not correlated to any ensemble, it seems strange that you would form a cross join of variants and ensembles from which to filter out rows. If that's really what you want, though, then this ought to do it:
SELECT *
FROM illuminavariant as vcf, ensembl_genes as ens
WHERE vcf.filter = "PASS"
AND vcf.qual > 100
AND (
vcf.chromosome != ens.chromosome
OR vcf.position < ens.start
OR vcf.position > ens.stop
)
That just negates the condition correlating variant rows with ensemble rows.
I suspect what you really want is more like this, though:
SELECT vcf.*
FROM
illuminavariant as vcf
LEFT JOIN ensembl_genes as ens
ON vcf.chromosome = ens.chromosome
AND vcf.position BETWEEN ens.start AND ens.stop
WHERE
vcf.filter = "PASS"
AND vcf.qual > 100
AND ens.chromosome IS NULL
That performs the same join as your first query, but as a left join. The rows that actually represent matches are then filtered out by the ens.chromosome IS NULL condition. It returns only the columns of the variant table, as the whole point is to find variants that have no corresponding row in the ensemble table.
try this...
SELECT *
FROM p7dev.illumina_test vcf
WHERE NOT EXISTS( SELECT 1
FROM p7dev.ensembl_test as ens
WHERE vcf.chromosome = ens.chromosome
AND vcf.position BETWEEN ens.start AND ens.stop
)
AND vcf.filter = 'PASS'
AND vcf.qual > 100
I'm migrating a project to Laravel 4 and I am stuck with a quite complex query, which I'd like to migrate into a proper Eloquent query.
I have a table that contains chat messages, called chat_messages with a representing Model Chatmessage
The table contains a sender and a receipient column with a user id linking to the users table and User Model.
The query to get a list with all user IDs of all chat partners in raw SQL on the old version of the application is as follows:
$sql_allChatPartners = "SELECT DISTINCT chatPartner
FROM ( SELECT * FROM (
SELECT cm_receipient AS chatPartner, cm_sent_at
FROM chat_messages WHERE cm_sender = '".$me->userID."'
UNION
SELECT cm_sender AS chatPartner, cm_sent_at
FROM chat_messages WHERE cm_receipient = '".$me->userID."'
) whateva ORDER BY whateva.cm_sent_at DESC ) other";
Sorry for naming the "fake" tables whateva and other :-)
Could anyone put me in the right direction to do this with Eloquent Querybuilder?
It is important that I get the list of chatPartner IDs in the correct order, where the last chat message has been exchanged as first chatPartner. And the chatPartner where longest inactivity was in the chat as last entry.
This is what I got so far in my User Model...
public function allopenchats(){
$asSender = Chatmessage::where('sender', $this->id)->select('receipient as chatPartner, created_at');
$asBoth = Chatmessage::where('receipient', $this->id)->select('sender as chatPartner, created_at')
->union($asSender)->orderBy('created_at', 'desc')->get();
}
I renamed the columns cm_receipient to receipient, cm_sender to sender and sent_at to created_at in the new database for the new version
Your help would be very much appreciated!
You sql may change to:
SELECT IF (cm_receipient = '10', cm_sender, IF (cm_sender = '10',cm_receipient, 'no')) AS chatPartner, cm_sent_at
FROM chat_messages
WHERE cm_receipient = '10' OR cm_sender = '10'
GROUP BY chatPartner
HAVING chatPartner != 'no'
order by cm_sent_at DESC
In orm:
Chatmessage::where('sender','=',$this->id)
->orWhere('receipient','=',$this->id)
->select(DB::raw('IF (receipient = '.$this->id.', sender, IF (sender = '.$this->id.',receipient, 'no' )) AS chatPartner'), 'created_at')
->groupBy('chatPartner')
->having('chatPartner', '!=', 'no')
->orderBy('created_at', 'desc')
->get();
Thanks very much to Vitalik_74, I wouldn't have come that far without him.
Here is now the final query, although its not in ORM, but it is working fine and gives me the result I need.
$result = DB::select("SELECT *
FROM (
SELECT IF( receipient = '".$this->id."', sender, IF( sender = '".$this->id."', receipient, 'no' ) ) AS chatPartner, created_at
FROM chatmessages
WHERE receipient = '".$this->id."'
OR sender = '".$this->id."'
HAVING chatPartner != 'no'
ORDER BY created_at DESC
)whateva
GROUP BY whateva.chatPartner
ORDER BY whateva.created_at DESC");
if there is someone out there who can do this query with the Laravel Query Builder, I would be happy to see it. For now I'll leave it like this.
I'm trying to query $wpdb to get back an int value of the number of users in a custom table who have recorded a number of hours volunteer work above a set target - these hours need to have been moderated ( value set to = 1 ) - I have this so far:
EDIT - updated to use consistent {} around php variables in query --
$target = get_post_meta($post->ID, 'target', true) ? (int)get_post_meta($post->ID, 'target', true) : 100;
$awards = $wpdb->get_var("
SELECT user_id
FROM {$this->options['rewards_logging']}
WHERE moderated = 1 AND reward_id = {$post->ID}
GROUP BY user_id
HAVING sum(hours) > {$target}
");
Which returns the correct value of '0' if none of the hours are approved ( moderated = 0 ), however as soon as one of those users hours are approved, this query returns the count of all the users who have logged more than the target hours ( whether they have been approved or not ).
Any pointers!
Cheers
Ray
Seems I was trying to get back a single variable using $wpdb->get_var, when I really needed the whole result set:
$awards = $wpdb->get_results("
SELECT user_id
FROM {$this->options['rewards_logging']}
WHERE moderated = 1 AND reward_id = {$post->ID}
GROUP BY user_id
HAVING sum(hours) > {$target}
");
Then I can check over the data and display a result - etc...:
if ( count($awards) > 0 ) {
#var_dump($awards);
echo '<span class="awards-notice">'.count($awards).'</span>';
} else {
echo '-';
}