Matching all values in IN clause - mysql

Is there a way to ensure all values in an IN clause are matched?
Example:
I can use IN as: IN (5,6,7,8).
I need it to work like an AND across multiple rows.
UPDATE:
I need this to list companies from db that fit specified parameters. Companies and taxonomy are MANY TO MANY relation. I'm using Yii framework. And this is the code of my controller:
public function actionFilters($list)
{
$companies = new CActiveDataProvider('Company', array(
'criteria' => array(
'condition'=> 'type=0',
'together' => true,
'order'=> 'rating DESC',
'with'=>array(
'taxonomy'=>array(
'condition'=>'term_id IN ('.$list.')',
)
),
),
));
$this->render('index', array(
'companies'=>$companies,
));
}

You can do something like this:
select ItemID
from ItemCategory
where CategoryID in (5,6,7,8) <-- de-dupe these before building IN clause
group by ItemID
having count(distinct CategoryID) = 4 <--this is the count of unique items in IN clause above
If you provide your schema and some sample data, I can provide a more relevant answer.
SQL Fiddle Example
If you want to find the items that have all of a specific set of CategoryIDs and no others, this is one way you can approach it:
select a.ItemID
from (
select ItemID, count(distinct CategoryID) as CategoryCount
from [dbo].[ItemCategory]
where CategoryID in (5,6,7,8)
group by ItemID
having count(distinct CategoryID) = 4
) a
inner join (
select ItemID, count(distinct CategoryID) as CategoryCount
from [dbo].[ItemCategory]
group by ItemID
) b on a.ItemID = b.ItemID and a.CategoryCount = b.CategoryCount
SQL Fiddle Example
If you prefer, you could do it with a subquery:
select ItemID
from ItemCategory
where ItemID in (
select ItemID
from ItemCategory
where CategoryID in (5,6,7,8)
group by ItemID
having count(distinct CategoryID) = 4
)
group by ItemID
having count(distinct CategoryID) = 4
SQL Fiddle Example

SELECT ItemID
FROM ItemCategory
WHERE (
(CategoryID = 5) OR
(CategoryID = 6) OR
(CategoryID = 7) OR
(CategoryID = 8)
)
GROUP BY ItemID
HAVING COUNT(DISTINCT CategoryID) = 4

Related

Laravel: get the most purchases product for current user

I have 3 tables here (order_lists, order_details, products)
Table order_lists contain the following user_id
Table order_details contain the following order_lists_id product_id
Table products contain all the products details.
the three tables are related to each others in models.
I need to select the most purchases items from table order_details based this user_id.
I made very basic Eloquent query which will select 6 products for this user but stuck on how to get the most purchases product
$mostPurchases = OrderList::where( 'user_id', Auth::id() )
->with( [
'orderDetails' => function ( $query ) {
$query->with( 'productId' );
}
] )->take( 6 )->get();
in order_details I need to count the user most purchases product.
UPDATE
As #party-ring suggest to use DB::raw query this is the final query looks like.
$usId = Auth::id();
$mostPurchases = DB::select( DB::raw( 'SELECT product_id, count(*) from order_details
LEFT JOIN order_lists ON order_details.order_lists_id = order_lists.id
WHERE order_lists.user_id = ' . $usId . '
group by product_id
order by count(*) DESC
LIMIT 6' ) );
Update
DB::table( 'products' )
->where( 'soft_delete', '!=', 1 )
->leftJoin( 'order_details', 'products.id', '=', 'order_details.product_id' )
->select( DB::raw( 'count(*) as pro_count, product_id' ) )
->leftJoin( 'order_lists', 'order_details.order_lists_id', '=', 'order_lists.id' )
->where( 'order_lists.user_id', '=', $usId )
->orderBy( 'pro_count', 'DESC' )
->groupBy( 'product_id' )
->take( 6 )
->get();
but still I got only the pro_count, and product_id
{
"pro_count": 22,
"product_id": 733
},
{
"pro_count": 15,
"product_id": 85
},
I need the product details within the response.
I would go about this by using join and DB::raw as I have found it can be more efficient than Eloquent when dealing with large datasets opposed to a function query - also I find it a little easier to build up my queries in this way.
select(DB::raw('SELECT product_id, count(*) from order_details
LEFT JOIN `order_lists` ON order_details.order_lists_id = order_lists.id
WHERE order_lists.user_id = :authUser
group by product_id
order by count(*) DESC
LIMIT 6', ['authUser => Auth::id()']);
You might need to play around with this a little as I don't know if you will need to specify the table names in your query.
This is adding together your order_lists and order_details tables, limiting it to that of the auth user, grouping it by the product id, ordering it by the count of those product purchases for the user and limiting it to 6 results.

Zf2 table gateway join query to fetch only the latest row(by id) from second table

Hi, I need a zf2 join query that fetches only the latest row(by id DESC) from the second table. I have written an sql query and it works.
SELECT st1.customer_id,
st1.id
FROM status st1
inner JOIN
(
SELECT max(id) MaxId, customer_id
FROM status
GROUP BY customer_id
) st2
ON st1.customer_id = st2.customer_id
AND st1.id = st2.MaxId
But I need this query at zend framework 2 table gateway format. Please help.
use Zend\Db\Sql\Select;
use Zend\Db\Sql\Expression;
$sql = new Select ();
$sql->columns(["customer_id", new Expression ("max(id) AS MaxId")])
->from ('status')
->group('customer_id');
$outer = new Select ();
$outer->columns (['customer_id', 'id'])
->from (['st1' => 'status'])
->join (['st2' => $sql],
'st1.customer_id = st2.customer_id AND st1.id = st2.MaxId', []);

Join two queries and group by two fields from two tables

I have those queries
SELECT CA_id, item_id, item_Cant, item_desc FROM items WHERE CA_id = 135
SELECT CA_id, prov_name, unitval, totval FROM provprices WHERE CA_id = 135 AND prov_name = 'SITECH'
and I want to join this two results, just like:
item_id - item_Cant - item_desc - unitval - totval
I tried diferent forms but the max that i can get is:
(If you notice the result from second table is dublicated, should be like the second image )
SELECT items.item_id,items.item_Cant,items.item_desc,provprices.unitval,provprices.totval
FROM items,provprices
WHERE items.CA_id = provprices.CA_id
AND provprices.prov_name = 'SITECH'
AND items.CA_id = '135'
GROUP BY items.item_id
If i change to GROUP BY provprices.unitval the duplicated result now is the first one
I hope you can help me. Thanks
I don't understand so much, but try this,
How do you wanna calculate the unitval and the totval
select item_id, item_Cant, item_desc, AVG(unitval), sum(totval)
from (
SELECT CA_id, item_id, item_Cant, item_desc
FROM items
WHERE CA_id = 135
) A
inner join (
SELECT CA_id, prov_name, unitval, totval
FROM provprices
WHERE CA_id = 135 AND prov_name = 'SITECH'
) B ON A.CA_id=B.CA_id
GROUP BY item_id, item_Cant, item_desc

JOINING 2 tables and pass values Into a Third Table

I have 2 tables namely ItemList table and ItemChara table, having this kind of structure:
wherein, Item_Num of Item Chara is a foreign key of Item List table. Now I'm trying to JOIN these tables. With a given like these.
How can I JOIN these tables with those values to form something Like this
I'm trying to find out what is the simplest way to achieve this. I limit the colors in table Item Chara at maximum of 2 colors per Item so it won't exceed 2 colors per item. I want to make another column like Color1 and Color2 to get each color in each item. If it happens that the item doesn't have a color to pair up with, it would just left blank, or null maybe.
Sorry but I'm not sure what to call the thing that I want to do but I know the output that I want to have, so the question title might be irrelevant. I'll change it as soon as I found out.
One way to do this is to use the row_number() window function:
select
i.item_num, i.item_name,
max(case when rn = 1 then ic.chara_color end) color1,
max(case when rn = 2 then ic.chara_color end) color2
from itemlist i
join (
select
item_num, chara_color,
rn = row_number() over (partition by item_num order by chara_num)
from itemchara
) ic on i.item_num = ic.item_num
group by i.item_num, item_name;
Below code will give u the required result.
select A.item_num,A.Item_name,
max(Color_1) AS Color_1,
max(Color_2) As Color_2
from (
select il.item_num,il.Item_name,
(case when ic.chara_num = 1 then ic.chara_color END) AS Color_1,
(case when ic.chara_num = 2 then ic.chara_color END) AS Color_2
from Item_List il inner join Item_Chara ic on il.Item_Num = ic.Item_Num
) A
group by item_num,Item_name
This code is not tested may be have some syntax erro which u need to check and sort it out. Let me know if still ur facing some issue.
Similar to other answers, but since I already made it I might post it anyway.
;with itemlist(itemId, itemName)
as
(
select 1,'Bag'
union ALL
select 2,'Pen'
union ALL
select 3,'Bike'
union ALL
select 4,'Shoes'
)
,itemchara(charaId, itemId, charaColor)
as
(
select 1, 1, 'Blue'
union all
select 2, 1, 'Red'
union all
select 3, 2, 'Black'
union all
select 4, 2, 'Blue'
union all
select 5, 3, 'Green'
union all
select 6, 4, 'Black'
)
,tmp
as
(
select i.itemName
,c.*
,row_number () over ( partition by c.itemId order by c.charaId ) as r
from itemlist i
join itemchara c
on i.itemId = c.itemId
)
select t1. itemId
,t1.itemName
,t1.charaColor
,t2.charaColor
from tmp t1
left join tmp t2
on t1.r+1 = t2.r
and t1.itemId = t2.itemId
where t1.r = 1

SQL Comparing 2 values that must be determined

I need to Find out the course with the most passes from my table tblResults.
tblResults:
StuID Course Symbol
1001 CSC101 P
1001 RNG101 F
1002 CSC101 P
1002 RNF101 F
1003 HAP101 P
1004 HAP101 P
i.e should give CSC101 (And all other courses (HAP101) with the same ammount of passes)
I have tried:
CREATE VIEW Part1 AS
SELECT NumbF
FROM
(SELECT COUNT(Course) AS NumbP,
Course
FROM tblResults
WHERE Symbol = 'P')
GROUP BY Course);
CREATE VIEW Part2 AS
SELECT MAX(NumbP) AS Maxnum
FROM Part1,
tblResults
WHERE Symbol = 'P'
GROUP BY Course;
SELECT Part1.Course
FROM Part1,
Part2
WHERE Part1.NumbP = Part2.MaxNum
But I seem to be doing something incorrectly. Please help
Something like this should work:
create view yourview as
select course, count(*) passcnt
from tblResults
where symbol = 'P'
group by course
select *
from yourview
where passcnt = (select max(passcnt) from yourview)
SQL Fiddle Demo
Note, you don't need the view, I just left it for simplicity.
SELECT Course, count(StuID) count
FROM tblResults
GROUP BY Course
HAVING count = (SELECT max(c)
FROM (SELECT count(StuID) c, Course
FROM tblResults
GROUP BY Course
WHERE Symbol = 'p'
) counts
);
You can try the SELECT below, but I haven't tested it:
SELECT selA.Course, selA.NumPass FROM (
SELECT Course, COUNT(Course) AS NumPass FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selA
INNER JOIN (
SELECT MAX(NumPassCount) AS NumPassMax FROM (
SELECT COUNT(Course) AS NumPassCount FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selB)
AS selC ON selA.NumPass = selC.NumPassMax
Using a couple of sub queries
SELECT Sub3.Course
FROM
(
SELECT MAX(Course) AS MaxCourseCnt
FROM
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub1
) Sub2
INNER JOIN
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub3
ON Sub2.MaxCourseCnt = Sub3.CourseCnt