Eloquent multiple select in the same query - php

Doing my firsts steps in eloquent, I'm trying to achieve a query that retrieve some data and count some conditions at the same time.
This raw SQL sentence works as expected
SELECT *
FROM photos,
(SELECT COUNT(*) FROM photos where type = 1 and published =1 group by type) as qA,
(SELECT COUNT(*) FROM photos where type = 2 and published =1 group by type) as qP
where product_id = 7
and published = 1
But using Photo model I can't get the same results
Photo::select(*,
Photo::raw('count(*) where type = 1 and published =1 group by type as qA),
Photo::raw('count(*) where type = 2 and published =1 group by type as qP))
->where ('product_id',7)
->where('published', 1)
->get()
Stripping out "raw" sentences, this query works, but I need to count those "type" ocurrences.
Thanks in advance for any guide over it.

Do you really need to get all in one query? Does it make sense for your application? I mean, I guess those types count are not really information about the record(s?) you are fetching (product_id = 7), rather they are general information about the state of the table as a whole.
If this makes sense, you could try
$photo = Photo::where ('product_id',7)
->where('published', 1)
->get();
$types_count = Photo::where('published', 1)
->selectRaw('type, COUNT(*) AS count')
->groupBy('type')
->get()
->keyBy('type');
$qA = $types_count[1]->count;
$qP = $types_count[2]->count;

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();

How can I order the results of an SQL query by the count of another table based on a shard ID?

I have an SQL query that fetches posts from a database. Everything works fine, but now I need to order the results by the number of comments each post has. The comments are on a separate table and they have a post_id column that links it to the post. I need to order the posts by the count of the comments table based on a shard ID? I have tried everything but every time I try to add something to my query it stops running completely and leaves my page blank. I need help to know where to put the other JOIN statement. This is my query:
$union = "UNION ALL
(
SELECT DISTINCT wallposts.p_id,wallposts.is_profile_notes,wallposts.times_viewed,wallposts.columnTimesShared,
wallposts.marked,wallposts.secure_id,wallposts.reshared,wallposts.group_id,
wallposts.totaluploads,wallposts.WallUploadID,wallposts.type,
wallposts.value,wallposts.media,wallposts.youtube,wallposts.post_type,
wallposts.privacy,wallposts.tagedpersons,wallposts.with_friends_tagged,wallposts.emotion_head,wallposts.selected_emotion,wallposts.title,
wallposts.url,wallposts.description,wallposts.cur_image,
wallposts.uip,wallposts.likes,wallposts.userid,
wallposts.posted_by,wallposts.post as postdata,wallusers.*,
UNIX_TIMESTAMP() - wallposts.date_created AS TimeSpent,
PosterTable.mem_pic as posterPic, PosterTable.gender as posterGender,PosterTable.oauth_uid as poster_oauth_uid, PosterTable.username as posterUsername,
PosterTable.mem_fname as posterFname,PosterTable.work as posterWork,
PosterTable.mem_lname as posterLname,walllikes_track.id as PostLikeFound,wallposts.date_created
FROM
wallusers,wallusers as PosterTable, wallposts
LEFT JOIN walllikes_track
ON wallposts.p_id = walllikes_track.post_id AND walllikes_track.member_id = ".$user_id."
WHERE
wallusers.active = 1
AND
PosterTable.active = 1
AND
wallposts.group_id IN (".$groups.")
AND
wallposts.group_id != 0
AND
PosterTable.mem_id = wallposts.posted_by
AND
wallposts.marked < ".$this->flagNumber."
AND
wallusers.mem_id = wallposts.posted_by ) ";
The comments table is called wallcomments and it has a column called post_id. I know I need to use JOIN and COUNT but I don't know where to put it within my current code.
Try this query, I didn't run but i updated it.
SELECT wallposts.p_id,wallposts.is_profile_notes,wallposts.times_viewed,wallposts.columnTimesShared,
wallposts.marked,wallposts.secure_id,wallposts.reshared,wallposts.group_id,
wallposts.totaluploads,wallposts.WallUploadID,wallposts.type,
wallposts.value,wallposts.media,wallposts.youtube,wallposts.post_type,
wallposts.privacy,wallposts.tagedpersons,wallposts.with_friends_tagged,wallposts.emotion_head,wallposts.selected_emotion,wallposts.title,
wallposts.url,wallposts.description,wallposts.cur_image,
wallposts.uip,wallposts.likes,wallposts.userid,
wallposts.posted_by,wallposts.post as postdata,wallusers.*,
UNIX_TIMESTAMP() - wallposts.date_created AS TimeSpent,
PosterTable.mem_pic as posterPic, PosterTable.gender as posterGender,PosterTable.oauth_uid as poster_oauth_uid, PosterTable.username as posterUsername,
PosterTable.mem_fname as posterFname,PosterTable.work as posterWork,
PosterTable.mem_lname as posterLname,walllikes_track.id as PostLikeFound,wallposts.date_created
FROM
wallusers,wallusers as PosterTable, wallposts
WHERE
wallusers.active = 1
AND
PosterTable.active = 1
AND
wallposts.group_id IN (".$groups.")
AND
wallposts.group_id != 0
AND
PosterTable.mem_id = wallposts.posted_by
AND
wallposts.marked < ".$this->flagNumber."
AND
wallusers.mem_id = wallposts.posted_by ) " AND wallposts.p_id = walllikes_track.post_id AND walllikes_track.member_id = ".$user_id.";
A more readable query might look like this...
At least then we'd have a chance.
SELECT DISTINCT p.p_id
, p.is_profile_notes
, p.times_viewed
, p.columnTimesShared
, p.marked
, p.secure_id
, p.media...
FROM wallposts p...

How to union 2 SQL-query in Codeigniter? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
UNION query with codeigniter's active record pattern
I have the following code:
$language_id=$this->get_language_id($language_code);
$english_id=$this->get_language_id('en');
$query="SELECT e.label_value, t.user_id, t.votes, t.approved, t.language_value FROM labels e left outer join labels t on e.label_value=t.label_value WHERE e.language=$english_id and t.language=$language_id and (t.approved=1 or t.user_id=$user_id) and e.label_value in (select distinct label_value from labels WHERE language=$english_id order by label_value limit $start_index, 30) order by e.label_value, t.votes";
$query=$this->db->query($query);
$data=$query->result_array();
But I have got the following error:
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
So, I need to do the folowoing part "select distinct label_value from labels WHERE language=$english_id order by label_value offset $start limit 30" in another query. Please, help me, how can I do it using CodeIgniter?
UPDATE:
There are is table labels
(label_value, language_value, language) - PK,
user_id,
timestamp,
approved,
votes
and I need to get all queries from this table (for example, it's name is t and e) with labels t.label_value, e.label_value (is exists), e.user_id, e.votes, e.timestamp where t.label_value=e.label_value(same label), t.language=45 (english language), e.language=24 (my language) and (e.user_id=121234 or e.approved=1). But I need all entries, and if (t.label_value!=e.label_value) I need to get this entry with NULL fields.
This is a limitation of MySQL and not PHP or CI. In order to get around it, you need to wrap your sub query in an aliased sub query so it becomes a derived table:
$language_id = $this->get_language_id($language_code);
$english_id = $this->get_language_id('en');
$query = "
SELECT e.label_value, t.user_id, t.votes, t.approved, t.language_value
FROM labels e
LEFT OUTER JOIN labels t on e.label_value=t.label_value
WHERE
e.language = $english_id
AND t.language = $language_id
AND (t.approved = 1 OR t.user_id = $user_id)
AND e.label_value IN (
SELECT label_value
FROM (
SELECT DISTINCT label_value
FROM labels
WHERE language = $english_id
ORDER BY label_value
LIMIT $start_index, 30
) i
)
ORDER BY e.label_value, t.votes
";
$query = $this->db->query($query);
$data = $query->result_array();
I think that will work, let me know if it doesn't and I will take another look at it.
EDIT
I'm having a little difficulty working out exactly what you are trying to do, but I think it might be something more like this:
SELECT t.label_value, t.user_id, t.votes, t.approved, t.language_value
FROM (
SELECT DISTINCT label_value
FROM labels
WHERE language = $english_id
) e
LEFT JOIN labels t ON e.label_value = t.label_value
WHERE
t.language = $language_id
AND (t.approved = 1 OR t.user_id = $user_id)
ORDER BY t.label_value, t.votes
LIMIT $start_index, 30
If this is still not correct, please show some example rows, and the result set you would like to retrieve from those rows.

mySQL query with JOIN on latest record not all records

The following code is used in a query for fetching records. It uses the electors.ID to find the corresponding voting_intention.elector from a second table.
$criteria = "FROM voting_intention,electors WHERE voting_intention.elector = electors.ID AND voting_intention.pledge IN ('C','P') AND electors.postal_vote = 1 AND electors.telephone > 0"
The problem is that some electors will have more than one pledge in the voting_intentions table.
I need it to match only on the latest voting_intention.pledge based on the field votin_intention.date for each elector.
What is the simplest way of implementing that.
The rest of the code:
function get_elector_phone($criteria){
$the_elector = mysql_query("SELECT * $criteria ORDER BY electors.ID ASC"); while($row = mysql_fetch_array($the_elector)) {
echo $row['ID'].','; }
}
You could use a sub-select with the MAX() function. Add the following into your WHERE clause.
AND voting_intention.date = (select MAX(date)
from voting_intention vote2
where voting_intention.elector = vote2.elector)
Here is a SQLFiddle of the results.
So pretty much, you only want to bother looking at the most recent row that fits the first two criteria in your code. In that case, you would want to filter out the voting_intention table beforehand to only have to worry about the most recent entries of each. There's a question/answer that shows how do do that here.
Try selecting the following instead of voting_intention (from the answer of the linked question, some table and field names replaced):
SELECT voting_intention.*
FROM voting_intention
INNER JOIN
(
SELECT elector, MAX(date) AS MaxDate
FROM voting_intention
GROUP BY elector
) groupedintention ON voting_intention.elector = groupedintention.elector
AND voting_intention.date = groupedintention .MaxDate
Question url: How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?

Order by a SUM with multiple joins in codeigniter

Solution:
$query = $this->db->query("
SELECT *, SUM(views.times) AS sum
FROM channel
RIGHT JOIN video
ON channel.channel_id = video.channel_id
LEFT JOIN user
ON channel.user_id = user.user_id
LEFT JOIN views
ON channel.channel_id = views.channel_id
GROUP BY channel.channel_name
ORDER BY sum DESC
");
I have a query that returns a list of items.
function getfrontpage(){
$this->db->select('*');
$this->db->from('channel');
$this->db->join('video', 'channel.channel_id = video.channel_id' , 'right');
$this->db->join('user', 'channel.user_id = user.user_id');
$this->db->group_by("channel.channel_name");
$query = $this->db->get();
return $query->result();
}
Now i'm trying to order these with the SUM from another table, how can i achieve this?
Here is a picture from that table:
I want the results to be sorted by the SUM of the total of "times" for each "channel_id"
thanks in advance
I would suggest to run this through $this->db->query() instead.
It's nice to fetch simple values through CodeIgniters AR functions. But at some situations it's simply easier to build query strings instead.
In your case:
$query = $this->db->query("
SELECT channel_id, SUM(times) AS sum
FROM channel
GROUP BY channel_id
ORDER BY sum DESC
");
You can also escape most values through db->query()!
$this->db->query("
SELECT name
FROM table_name
WHERE id = ?
", array(1));
Isn't it as simple as $this->db->order_by("channel_id", "desc");? this orders the results by channel_id in descending order.
Assuming the table displayed in your question is called times_table, and has a key of user_id, channel_id, you can use the following code to join the times_table into your query so the "times" column is available to sort by.
$this->db->join("times_table", "times.user_id=channel.user_id, times.channel_id=channel.channel_id", "left");
// You've already grouped by channel_name, so grouping by channel_id is probably not necessary.
$this->db->order_by("SUM(times_table.times) DESC");
N.B. I just guessed the name of your displayed table is times_table.

Categories