How can I order query by another table? - php

I have a long query, but I keep it simplified:
$query = $this->db->query(" SELECT id FROM oc_products ORDER BY ...? ");
Here is the problem. In this table I have all the products, but I have a second table, oc_seller_products, where I have same column ID, which match with oc_products.
I want to be ordered first id's which dont appear in oc_seller_products, and at last, appear id's which appear in oc_seller_products.
For example: in oc_products I have ID: 1,2,3,4,5
In oc_seller_products I have only ID: 4
I need to be ordered like this: 5,3,2,1 and the last: 4
I have a marketplace, so I want first my products to appear, on category page, then my sellers products.
I really have no idea how to do that.

select op.id
from oc_products op
left join oc_seller_products osp using (id)
order by osp.id is null desc, op.id desc
osp.id is null will be 1 when there is not an oc_seller_products record and 0 when there is, so sort by that, descending, first. And then after that, within those two categories, you seem to want descending id order.

Related

How to use COALESCE in Laravel?

Is it possible to use COALESCE in laravel query?
$multipleitems = DB::table('votes')
->select('masterItemId',DB::raw('sum(votes) as voteSum'))
->whereBetween('voteDate',array($startDate,$endDate))
->where($condition)
->groupBy('masterItemId')
->get();
In the above code I want to get each item and its total votes. If there is no vote I want to get '0'.
But in the above code it returns items that have atleast one vote. Is there any method to get this done in laravel?
Well, the OP was not too helpful, but I will give it a shot! I assume, that the votes table contains actual votes cast by users on the items. This means, that if an item did not receive any vote, then that item id (masterItemId) does not exist in the votes table.
This means that the votes table has to be left joined on the main items table on the masterItemId field. I will call the main items table: items, and assume that it has an itemId field that matches the masterItemId field in the votes table. In SQL terms:
select items.itemId, ifnull(sum(votes.votes),0) as votesSum
from items left join votes on items.itemId=votes.masterItemId
where votes.voteDate between ... and ... and <other conditions>
group by items.itemId
I'm not familiar with Laravel, but you will need something like this, however do not treat is as copy-paste code:
$multipleitems = DB::table('items')
->leftJoin('votes','items.itemId','=','votes.masterItemId')
->select('items.itemId',DB::raw('ifnull(sum(votes.votes),0) as voteSum'))
->whereBetween('votes.voteDate',array($startDate,$endDate))
->where($condition)
->groupBy('items.temId')
->get();

Getting Total Votes Form mysql table and Compare it?

I have a table with
id primary key, nominee_id, cat_id, user_id(voter id), vote_status, date
these fields, We have nominees for this voting process under different categories, so each nominees can be nimnated to more than one category. ok, all process is going well, I can take total count of votes got for each nominees in each category. but I dont have any idea How to get the winner from this table using SQL.
I want to get Most votes gained Nominees in each category, however as I said I can get total votes got for each nominees in each category using
SELECT nominee_id FROM voting WHEREcat_id= $cid.
Is it possible get this through another SQL statement, or else can anyone suggest any other way to get this.
below is the table, I want to get back the Nominee_id who got max Vote in a particulat cat_id, eg: in hte below table I want to get nominee_id 29 as a winner in cat_id 3, because he got two votes in that category
This query will give you the winner from each category.
SELECT nid, cid, max(votes) as final_votes from (select nominee_id as nid, cat_id as cid, count(user_id) as votes from voting group by cat_id, nominee_id) nv GROUP BY cid order by final_votes desc;
This one should work
SELECT nominee_id, COUNT(nominee_id) AS countNominee FROM voting WHERE
vote_status = 'yes' GROUP BY cat_id ORDER BY countNominee DESC

Sorting count in multiple tables

I'm working on a PHP/mySQL table that shows data I've put into my database, and I'm trying to make it sortable. I have two tables in my database:
Table "restaurant" has columns: ID and name
Table "item" has columns: ID, name and restaurantID (restaurantID is set to use the IDs from the "restaurant" table)
What I want to do is sort the restaurants by the number of times their ID shows up in the item table. I'm sure there must be a simple way to do this, Just haven't been able to figure it out. Any help would be greatly appreciated!
Try this...
select r.name, count(i.ID)
from restaurant r
left join item i on i.restaurantID = r.ID
group by r.name
order by count(i.ID) desc
I believe you can do it by using a query like following;
SELECT restaurant.*, COUNT(items.id) AS item_id FROM restaurants, items WHERE restaurant.id = items.restaurant_id ORDER BY item_id ASC;
As you may know, sorting by multiple column is possible as well;
SELECT restaurant.*, COUNT(items.id) AS item_id FROM restaurants, items WHERE restaurant.id = items.restaurant_id ORDER BY item_id ASC, restaurant.`name` DESC;

php mysql inner join - get a particular row

This is my query to get model information from one table and a single picture from another table. What changes do I have to make to this query in order for it to get the picture where ORDER BY sort DESC? In the table of the pictures, there is a field by the name "sort". The default value for the field for each row is 0. But one random row has the value of 1. I want to get that particular row. I don't, however, want to use WHERE sort=1 because then even in the case where no row has the sort value 1, one row should still get fetched.
$sql="SELECT tc.id,tc.alias,tc.firstname,tci.imagename
FROM ".$pre."models tc
INNER JOIN ".$pre."model_images tci ON tc.id=tci.userid
WHERE activated=1 AND sex=$sex AND city=$city AND published=1
GROUP BY tc.id ORDER BY firstname ASC";
Thank you in advance!
Solved using:
SELECT tc.id,tc.alias,tc.firstname,
(SELECT imagename FROM ".$pre."model_images WHERE userid= tc.id
ORDER BY sort DESC LIMIT 1) AS imagename
FROM ".$pre."models tc
WHERE tc.activated=1 AND tc.sex=1 AND tc.city=2 AND tc.published=1
ORDER BY tc.firstname ASC
You should place that in your WHERE clause aswell. One t hing to note though is to be carefull with the way you're using the column names. It's better to tell to which table they belong.
So this:
WHERE activated=1 AND sex=$sex AND city=$city AND published=1
Should be:
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1
And then simply add the 'sort' column to it:
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1 AND tci.sort=1
If no results are returned, then make sure that there are records that meet the required conditions. Because there's nothing wrong with the query. Try to print your query to the screen etc. to see if every variables has a value.
edit:
You should lose the GROUP BY.
SELECT tc.id,tc.alias,tc.firstname,tci.imagename
FROM ".$pre."models tc
INNER JOIN ".$pre."model_images tci ON tc.id=tci.userid
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1 AND tci.sort=1

PHP/MySQL: Many-to-many/intersect table question

I'm not really sure how to phrase the question, so let me just give an example of the problem:
Suppose there's a table which maps items to categories. Each item can have any number of categories, and each category can of course hold any number of items. So you have a table that looks like this:
items_categories
id item_id category_id
The problem is, I want to select all item id's which have specific category id's. For example, select all item_id's with category_id's of 1 and 2: I want to find all items that are associated with categories both 1 and 2. Obviously I can't use an AND statement, and an OR statement would return all item_id's with either category, but not necessarily both.
Here is my solution and the best thing I can think of: select all item_ids with category_id equal to 1 OR 2; iterate through the results in PHP and keep track of how many item_ids are associated with a category_id; and then unset all item_ids in the results that don't have the specified number of categories. Here's a snippet of my code:
// assume $results is an array of rows from the db
// query: SELECT * FROM items_categories WHERE category_id = 1 OR category_id = 2;
$out = array();
foreach ($results as $result)
{
if (isset($out[$result['item_id']]))
$out[$result['item_id']] ++;
else
$out[$result['item_id']] = 1;
}
foreach ($out as $key=>$value)
{
if ($value != 2)
unset($out($key));
}
return array_keys($out); // returns array of item_ids
Obviously if you have lots of different categories, you're selecting and processing way more information than you should theoretically need to. Any ideas?
Thanks!
Edit: Here's an example of a table and the information I want from it:
id item_id category_id
1 1 1
2 1 2
3 2 1
4 3 2
So say I'm interested in getting all of the items with categories 1 and 2. How do I get item #1 from my example table, given that I want only items with categories #1 and #2? If I select everything with categories 1 or 2 (as in my example above), I have to select the whole table in this case and "manually" remove item_id's 2 and 3, since they aren't associated with both category 1 and category 2. Hope this helps clarify a little.
Final edit: I figured it out, despite my apparent inability to describe what I'm trying to do, heh. Here's the query I came up with, for the record:
SELECT *
FROM
(
SELECT item_id, COUNT(*) as count
FROM items_categories
WHERE category_id IN (1, 2)
GROUP BY item_id
) table_count
WHERE count = 2;
In this case, the "(1, 2)" could be replaced with "(category_id1, category_id2, ...)", and the "2" at the end would be replaced with the number of categories I'm searching for.
So it finds out how many categories match the criteria for each item, and since I only want items where ALL the categories match, it only selects those where the number of categories equals the number of categories I'm looking for. This is of course assuming there are no duplicate categories or anything like that.
Thanks for the responses!
It seems that what is troubling you is that you are forced to do a linear search which of course takes O(n) time, but if you select elements from your database in sorted order, then can't you just use a binary search in O(lg n) time?
I hope this helps, If not, then maybe I misunderstood your question and I'd like you to clarify it a little bit.
SELECT
foo
FROM
bar
WHERE
foo IN (1,2)
is this what you are looking for?
This is something you should be getting the database to do rather than PHP.
SELECT item_id # We want a list of item ids
FROM cat_items # Gets the item ID list from the cat_items table
WHERE cat_id IN (1, 2, 7, 11) # List of categories you want to search in
GROUP BY item_id; # As the same item can appear in more than one category this line will eliminate duplicates
This query does assume that the data in cat_items is accurate, in other words that the category and item IDs point to valid entries in the categories and items tables respectively. If you're using a database with foreign key support (The InnoDB engine for MySQL, Postgres, etc) enforcing foreign keys is not difficult.
To get a list of IDs in each category in the format you want, that's easily done on the SQL side too.
SELECT *
FROM cat_items
WHERE cat_id IN (1, 2, 7, 11)
GROUP BY cat_id, item_id;
If you just want a count of how many items are in each category you can also do that in SQL
SELECT cat_id, COUNT(item_id) AS items
FROM cat_items
WHERE cat_id IN (1, 2, 7, 11)
GROUP BY cat_id;
If you need more data than just the ID then you can join against the table you need the data from.
SELECT items.*
FROM cat_items
JOIN items ON cat_items.item_id = items.id
WHERE cat_id IN (1, 2, 7, 11)
GROUP BY item_id;
SELECT item_id FROM items_categories WHERE category_id = 1 AND item_id IN (SELECT item_id FROM items_categories WHERE category_id = 2)

Categories