I'm building Laravel 5.4 web application and I have below database table:
==================================
product_id|attribute_id|option_id
==================================
1 | 1 | 1
1 | 2 | 3
1 | 4 | 10
2 | 1 | 1
2 | 2 | 4
... etc
So i submit form with attributes id and options id so i can build array from it or whatever.
What i want to achieve that I select from the database the product_id which match exact combination for example:
[
attribute_id => 1,
option_id => 1
attribute_id => 2,
option_id => 3
attribute_id => 4,
option_id => 10
]
This condition only apply to product with product_id = 1
Don't know if i can do it using database query or by php.
First, make a model that reflects your data. Then use the Eloquent query builder to get the data you're looking for. If you need just one number returned that matches, make sure to add on to the end the query "->distinct()".
You may also pass an array of conditions to the 'where' clause.
Your code may look something like this:
$match = DB::table('products')
->where('attribute_id', 1)
->where('option_id', 1)
->distinct()
->get();
https://laravel.com/docs/5.4/queries#introduction
If you just want the product with product_id = 1
Assumed you have stored this in "product_attribute_option" table
and its fields are product_id |attribute_id | option_id as you shown.
$query = DB::table('product_attribute_option as pao');
$query->where('pao.product_id', 1);
$results = $query->get();
Related
I am displaying a list of items where I want the highest point to appear first irrespective of how the data is sorted. At first the snippet that does the logic is working but when inputed with different variables as shown in the table structure, the expected logic output fails. Here is the entity structure
books.php
id | name | points | active
1 | huk | 5 | true
2 | foo | 2 | true
3 | doo | 2 | true
4 | jack | 12 | true
Here is my controller snippets
$restresults = $this->getDoctrine()
->getRepository('xxxBundle:Books')
->findBy(
['active' => true],
['points' => 'DESC']
);
the above snippets result is unpredictable from my coding intention, as it returns this result in sorting in respect to book points 5, 2, 2, 12 instead of 12, 5 , 2 , 2.
Please what could be wrong with my algorithm
Looking at sorting result it looks like the string type is sorted instead of int.
To fix that change the type of column points to int both in doctrine and db for example with #Column(type="integer") */ depending on your style of mapping.
The other way is to make DQL. If you can't do it then you need to make your own DQL
and write orderby there.
Ex.
$books = $em->getRepository('xxxBundle:Books')
->createQueryBuilder('q')
->addSelect('ABS(q.points) AS HIDDEN pointsOrder') // other way CAST(q.points AS UNSIGNED)
->orderBy('pointsOrder', 'DESC)
->getQuery()
->getResult();
I need to write an ActiveRecord query where I get all fields of rows without duplicates in one field.
Example: Here is a table of books. I want to get all data of the rows with
distinct isbn. From duplicates the first row should be taken. The result should be the rows with id 1,2,4
id | title | isbn
--- | ------- | ------
1 | hello | 1001
2 | world | 1002
3 | this | 1002
4 | is | 1003
5 | funny | 1003
My first attempt was
$books = Books::find()->select('isbn')->distinct()->all();
but that fills only the isbn field in $books[0], $books[1], ....
Is this possible using Yii2 ActiveRecord?
You may use groupBy() for this:
$books = Books::find()->groupBy(['isbn'])->all();
But this returns random row with matching isbn value and may not work in some DBMS. Your requirements are too ambiguous to handle it in predictable way. But if you want always first row, you may use subquery to fetch matching isbn and id:
$query = (new Query())
->select(['MIN(id) as id, isbn'])
->from(Books::tableName())
->groupBy(['isbn']);
return Books::find()
->alias('book')
->innerJoin(['subquery' => $query], 'book.id = subquery.id AND book.id = subquery.id')
->all();
The description given in Yii2 for the distinct property is as follows:
Whether to select distinct rows of data only. If this is set true, the SELECT clause would be changed to SELECT DISTINCT.
-- https://www.yiiframework.com/doc/api/2.0/yii-db-query#$distinct-detail
therefore you should pass true with distinct property if you need to select the distinct values of 'isbn' as follows:
$books = Books::find()->select('isbn')->distinct(true)->all();
I want to get all the purchases and their sums and also I don't want to add the amount if payments.deleted_at is not null.
Here are the tables
purchases
id | name
1 | Gamerzone Book
2 | Recipe Book
3 | EngineX Book
payments
id | purchase_id | amount | deleted_at
1 1 100 2015-06-12 11:00:00
2 2 50 NULL
2 2 10 NULL
Code
$query = DB::table('purchases')
->select(['purchases.*',
DB::raw("IFNULL(sum(payments.amount),0) as total")
])
->leftJoin('payments','payments.purchase_id','=','purchases.id')
->whereNull('payments.deleted_at')
->groupBy('purchases.id')->get();
When I run the code below the 1st result is not included.
Result
id | name | total
2 | Recipe Book 60
3 | EngineX Book 0
I know why It is not included but the problem is if I remove whereNull('payments.deleted_at') that particular row in payments
will also add to the sum.How should I solve this ??
Expected Result
id | name | total
1 | Gamerzone Book 0
2 | Recipe Book 60
3 | EngineX Book 0
In this case your join condition should looks like this:
ON (payments.booking_id = purchases.id AND payments.deleted_at IS NOT NULL)
And it is not about WHERE (according to your SELECT).
You should use join-closure like this:
$query = DB::table('purchases')
->select(['purchases.*', DB::raw("IFNULL(sum(payments.amount),0) as total")])
->leftJoin('payments', function($join) {
$join->on('payments.booking_id', '=', 'purchases.id');
$join->on('payments.deleted_at', 'IS', DB::raw('NOT NULL'));
})
->groupBy('purchases.id')->get();
Just replace
->leftJoin('payments','payments.booking_id','=','purchases.id')
with
->leftJoin('payments', function($join) {
$join->on('payments.booking_id', '=', 'purchases.id');
$join->on('payments.deleted_at', 'IS', DB::raw('NOT NULL'));
})
and remove this:
->whereNull('payments.deleted_at')
it should help.
I have two tables in Laravel of which I am seeking to merge them together, however, I want to return every single value of the first table (without duplicates) along with only values from the second table that have a FK value of 2. If there is no entry with a FK of 2, it joins with a value of null.
To make my question a little more clear, lets say we have the following tables:
TV Shows Table
ID | Show
1 | First Show
2 | Second Show
3 | Third Show
Favorites Table
Show_ID | Member_ID
1 | 1
3 | 1
1 | 2
2 | 2
I am looking to merge them into a resultant set like the following when I join the tables with a member ID of 2(disregarding the joined 'Show_ID' column):
Merged Table
ID | Show | Member_ID
1 | First Show | 2
2 | Second Show | 2
3 | Third Show | null
Thanks.
Not 100% I understood, so hope this is what you're looking for.
I've renamed some of the column names to make things a little clearer.
DB::table('shows')
->select(
'shows.id as show_id',
'shows.name as show_name',
'member.id as member_id'
)
->leftJoin('favourites', 'shows.id', '=', 'favourites.show_id')
->get();
Left join will allow there to be null in member_id if it isn't present on the join.
You can add this to restrict to member ID of two:
DB::table('shows')
->select(
'shows.id as show_id',
'shows.name as show_name',
'member.id as member_id'
)
->leftJoin('favourites', 'shows.id', '=', 'favourites.show_id')
->where('member.id', 2)
->get();
I solved it myself. I needed to do a functional join like so:
DB::table('shows')
->leftJoin('favorites', function($q) use $memberID)
{
$q->on('shows.ID', '=', 'favorites.show_ID')
->where('favorites.member_ID', '=', $memberID);
})->get();
Use table with structure:
id | count
/string/id1 | 3
/string/id1/r1 | 2
/string/id1/r2 | 1
/string/id2/r1 | 2
/string/id2 | 3
/string/id2/r1 | 2
/string/id3/r1 | 5
and I want to select all rows which have needed substring in id.
i.e.
I need all rows which have substring in id: /string/id1 and /string/id2
The query should be easy - plain sql:
select * from table_name where id LIKE '/string/id1%' OR id LIKE '/string/id2%';
Result should be:
id | count
/string/id1 | 3
/string/id1/r1 | 2
/string/id1/r2 | 1
/string/id2/r1 | 2
/string/id2 | 3
/string/id2/r1 | 2
Unfortunately, if you try to use the same query in symfony and doctrine2:
$ids = array('/string/id1', '/string/id2');
$query = $this->createQueryBuilder('r')
->select('r');
foreach ($ids as $id) {
$query->orWhere("r.linkedId LIKE :id ")
->setParameter('id', $id."%");
}
$plainQuery = $query->getQuery()->getSQL();
$results = $query->getQuery()->getResult();
Plain query looks the same like select * from table_name where id LIKE '/string/id1%' OR id LIKE '/string/id2%';, but results are not.
results contains only rows of last item in ids - /string/id2
id | count
/string/id2/r1 | 2
/string/id2 | 3
/string/id2/r1 | 2
How to solve it? Where is my mistake? Do you have any suggestion?
I cannot be sure but this seems to me like a conflict with parameter identifiers.
This is what you're trying to do:
Construct the basic SELECT * FROM table_name statement
Append WHERE r.linkedId LIKE :id
set the value of id parameter to /string/id1%
Append OR r.linkedId LIKE :id
set the value of id parameter to /string/id2% (override the previous value) <-- AN ERROR
Basically, you are telling Doctrine to override previously defined value of id parameter with new one.
You could easily overcome this issue. Just add $i to parameter name
foreach ($ids as $i => $id) {
// $i here has the value of 0,1,2, etc...
$query->orWhere("r.linkedId LIKE :id$i" ) // append $i
->setParameter("id$i", $id."%"); // but also append it here
}
Be sure to use double quotes, or concatenate ("id" . $i) instead ;)