Get last price by user role? - sql

How do I get the last price claimed by the retailer b#gmail.com (the 5th row in the price table) with the condition that the role = 'retailer' ?
So here is my simple table:
table users (using Entrust Role package with the default relationship in the model)
__________________________
| id | email | password |
|-------------------------|
| 1 | a#g.com | 123 |
| 2 | b#g.com | 123 |
| 3 c#g.com | 123 |
| 4 d#g.com | 123 |
--------------------------
table roles (using Entrust Role package with the default relationship in the model)
______________
|id | name |
|--------------|
|1 | customer |
|2 | retailer |
----------------
table role_user (using Entrust Role package with the default relationship in the model)
__________________
|id_user | id_role|
|------------------|
| 1 | 1 | -> a#gmail.com is a customer
| 2 | 2 | -> b#gmail.com is a retailer
| 3 | 1 | -> c#gmail.com is a customer
| 4 | 1 | -> d#gmail.com is a customer
------------------
Here is the tricky part how to query the price:
I have the following prices table (Users can post 1 or more prices. Look at the relationship below):
____________________
|id| user_id| price |
|--------------------|
|1 | 1 | 10.00 | -> price claimed by a customer a#gmail.com
|2 | 2 | 5.00 | -> price claimed by a retailer b#gmail.com
|3 | 1 | 6.00 | -> price claimed by a previous customer a#gmail.com
|4 | 3 | 5.00 | -> price claimed by a customer c#gmail.com
|5 | 2 | 7.00 | -> price claimed by a previous retailer b#gmail.com //How to get this one? This is the last price claimed by the retailer.
|6 | 3 | 8.00 | -> price claim by a customer c#gmail.com
---------------------
The relationship in my Price model:
class Price extends Model{
public function product()
{
return $this->belongsTo('App\Product');
}
public function user()
{
return $this->belongsTo('App\User');
}
How do I get the last price claimed by the retailer b#gmail.com (the 5th row in the price table) with the condition that the role = 'retailer' ?
The purpose is to get the last price that the retailer has claimed.
Update my question:
I want to access the price claimed by the last retailer from my Product model using the $products variable.
A sample table product that I have:
_______________________________
|id | user_id| name |
|------------------------------
| 1 | 1 | Milk |
| 2 | 2 | Phone |
| 3 | 1 | computer |
| 4 | 1 | Banana |
------------------------------
My Product.php model relationship:
class Product extends Model{
public function prices()
{
return $this->hasMany('App\Price');
}
}
So, in my ProductController.php I send the $product variable to the view like this:
class ProductController extends Controller
{
public function show($id)
{
$product = Product::where('id', '=', $id)->
return view('products.show')->with('product', $product);
}
}
and in my view show.blade.php, I loop through the $product variables and I can display the prices claimed for the product.
#foreach($product->prices as $price)
<li>Price claimed: {{$price->price. " " }} </li>
#endforeach
I want to get like something like
$price_last = $product->prices()->where(role, 'retailer')->last().
dd($price_last);
The last() function there is the last price that the retailer claimed but this code is just example. How do I achieve this?
Please let me know if you need more information.

You're looking for the whereHas method:
$query = Price::latest('id')->whereHas('user', function ($query) {
$query->whereHas('role', function ($query) {
$query->where('name', 'retailer');
});
});
$price = $query->value('price');
This assumes you've set up the relationships between your User, Role and Price models.

Related

Trying to use SQL to group accounts by number of sub-types

I'm using a table that houses account info. These accounts can have between 1 and 6 unique sub types. Currently it only tracks between single and multi subtypes but doesn't show the totals of how many of each multi sub-type account there are (how many accounts with 2 subtypes vs. 3 subtypes and so on). I'm looking for a wholly SQL way to view how many of each grouping of account types. There are a LOT of accounts in the table so pulling it manually isn't really an option. Is there a way I can get a count of each of the amount of sub-type groupings?
| account | Sub-Type | Single_V_Multi |
|---------|--------- | -------------- |
|123456789|123456789 | Multi |
|123456789|123456790 | Multi |
|123456789|123456791 | Multi |
|123456792|123456792 | Single |
|123456793|123456793 | Multi |
|123456793|123456794 | Multi |
|123456795|123456795 | Single |
|123456796|123456796 | Single |
|123456797|123456797 | Single |
|123456798|123456798 | Single |
|123456799|123456799 | Multi |
|123456799|123456800 | Multi |
|123456799|123456801 | Multi |
|123456799|123456802 | Multi |
From this example I'd be looking to get separate counts of the Account column based on the number of unique Sub-Type. What I've done so far is a query that groups the Sub-Types:
SELECT account, COUNT(DISTINCT(Sub-Type)) as BAN_SUB_COUNT
FROM Table
Which give the output:
| account | BAN_SUB_COUNT |
| ------- | ------------- |
|123456789| 3 |
|123456792| 1 |
|123456793| 2 |
|123456795| 1 |
|123456796| 1 |
|123456797| 1 |
|123456798| 1 |
|123456799| 4 |
What I need from this is a way to get a separate count of accounts for each of the distinct BAN_SUB_COUNT entries. Ideally it would be along the lines of:
| BAN_SUB_COUNT |count of Accounts|
| ------------- | --------------- |
| 1 | 5 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
Sorry for any confusion and I hope I'm explaining myself better here!
You just need to wrap your query with another one:
select ban_sub_count, count(distinct account) as count_of_accounts
from (
SELECT account, COUNT(DISTINCT Sub-Type ) as BAN_SUB_COUNT
FROM Table
group by account
)z
group by ban_sub_count
Output:
BAN_SUB_COUNT
count of Accounts
1
5
2
1
3
1
4
1
I try to answer your question:
select a2.*,a.`count_sub_type`
FROM (
select count(`sub-type`) as count_sub_type,`sub-type` from account group by `sub-type`
) a
left join account a2 on a2.`sub-type` = a.`sub-type`;
output :
|account |sub-type|single_v_multi|count_sub_type|
|--------|--------|--------------|--------------|
|account6|type1 |multiview |3 |
|account5|type1 |single |3 |
|account1|type1 |single |3 |
|account4|type2 |single |2 |
|account2|type2 |single |2 |
|account6|type3 |single |2 |
|account3|type3 |single |2 |
Best regards,

PowerBI / SQL Query to verify records

I am working on a PowerBI report that is grabbing information from SQL and I cannot find a way to solve my problem using PowerBI or how to write the required code. My first table, Certifications, includes a list of certifications and required trainings that must be obtained in order to have an active certification.
My second table, UserCertifications, includes a list of UserIDs, certifications, and the trainings associated with a certification.
How can I write a SQL code or PowerBI measure to tell if a user has all required trainings for a certification? ie, if UserID 1 has the A certification, how can I verify that they have the TrainingIDs of 1, 10, and 150 associated with it?
Certifications:
CertificationsTable
UserCertifications:
UserCertificationsTable
This is a DAX pattern to test if contains at least some values.
| Certifications |
|----------------|------------|
| Certification | TrainingID |
|----------------|------------|
| A | 1 |
| A | 10 |
| A | 150 |
| B | 7 |
| B | 9 |
| UserCertifications |
|--------------------|---------------|----------|
| UserID | Certification | Training |
|--------------------|---------------|----------|
| 1 | A | 1 |
| 1 | A | 10 |
| 1 | A | 300 |
| 2 | A | 150 |
| 2 | B | 9 |
| 2 | B | 90 |
| 3 | A | 7 |
| 4 | A | 1 |
| 4 | A | 10 |
| 4 | A | 150 |
| 4 | A | 1000 |
In the above scenario, DAX needs to find out if the mandatory trainings (Certifications[TrainingID]) by Certifications[Certification] is completed by
UserCertifications[UserID ]&&UserCertifications[Certifications] partition.
In the above scenario, DAX should only return true for UserCertifications[UserID ]=4 as it is the only User that completed at least all the mandatory trainings.
The way to achieve this is through the following measure
areAllMandatoryTrainingCompleted =
VAR _alreadyCompleted =
CONCATENATEX (
UserCertifications,
UserCertifications[Training],
"-",
UserCertifications[Training]
) // what is completed in the fact Table; the fourth argument is very important as it decides the sort order
VAR _0 =
MAX ( UserCertifications[Certification] )
VAR _supposedToComplete =
CONCATENATEX (
FILTER ( Certifications, Certifications[Certification] = _0 ),
Certifications[TrainingID],
"-",
Certifications[TrainingID]
) // what is comeleted in the training Table; the fourth argument is very important as it decides the sort order
VAR _isMandatoryTrainingCompleted =
CONTAINSSTRING ( _alreadyCompleted, _supposedToComplete ) // CONTAINSSTRING (<Within Text>,<Search Text>); return true false
RETURN
_isMandatoryTrainingCompleted

Laravel 7 query relationships tables

I need a bit of help with getting data from tables that are in relationship.
I have 2 tables: cards and statuses:
I have following data in cards table:
id_card | card_type
--------|----------
123 | tag
281 | card
455 | card
721 | tag
In statuses table I have:
id_status | id_card | status_date | status_type | status_company | status_user
----------|---------|-------------|-------------|----------------|------------
1 | 123 | 2018-12-04 | available | |
2 | 281 | 2018-12-04 | available | |
3 | 455 | 2018-12-04 | available | |
4 | 721 | 2019-03-26 | available | |
5 | 281 | 2020-01-25 | issued | Company A | User One
6 | 123 | 2020-01-10 | issued | Company B | User Two
7 | 281 | 2020-01-25 | available | |
8 | 123 | 2020-02-02 | lost | |
9 | 455 | 2020-02-14 | issued | Company C | Third User
For table cards I have following in Card model:
public function Status() {
return $this->hasMany('App\Status', 'id_card', 'id_card')
->orderBy('status_date', 'desc');
}
And for statuses table I have in Status model:
public function Card() {
return $this->hasOne('App\Card', 'id_card', 'id_card')
}
Now, how should I write a query, that would return me list of cards together with values from statuses table, but only with latest status for each card, like this:
id_card | card_type | status_type | status_date | status_company | status_user
--------|-----------|-------------|-------------|----------------|------------
123 | tag | lost | 2020-02-02 | |
281 | card | available | 2020-01-25 | |
455 | card | issued | 2020-02-14 | Company C | Third User
721 | tag | available | 2019-03-26 |
And is there a way, to also filter such a query i.e. to get only available cards:
id_card | card_type | status_type | status_date | status_company | status_user
--------|-----------|-------------|-------------|----------------|------------
281 | card | available | 2020-01-25 | |
721 | tag | available | 2019-03-26 | |
Thank you very much in advance :)
For getting all the cards having status_type 'available'
Card::join('statuses', 'cards.id_card', '=', 'statuses.id_card')
->where('statuses.status_type', 'available')
->select('cards.id_card', 'cards.card_type', 'statuses.status_type', 'statuses.status_date', 'statuses.status_company', 'statuses.status_user')
->get();
For getting latest status you can follow these steps,
Add following method in Card model
public function latestStatus()
{
return $this->hasOne('\App\Status')->latest();
}
Method latest() orders all rows by created_at desc, and takes the first one. If you don't have created_at column you can add it in statuses table.
$cards = Card::with('latestStatus')->get();
foreach ($cards as $card) {
echo $card->type . ' has latest status of ' . $card->latestStatus->status_type;
}
last but not the least, I think if you follow laravel conventions then you'll already have half of your problem solved.
Laravel is a framework that works better for you if you follow some conventions. The database models standards in Laravel in your case for Card and Status would be:
Then, you could simply have:
Status.php
use App\Card;
class Status extends Model
{
public function card()
{
return $this->hasOne(Card::class);
}
}
Card.php
use App\Status;
class Card extends Model
{
public function statuses()
{
return $this->hasMany(Status::class);
}
}
Finally, you could do:
$cards = App\Card::with(['statuses' => function($q){
$q->latest()->take(1);
}])->get();
Laravel will give out of the box a collection of Cards, with the last status attached.
To filter results based in related Status you could do:
$filter = 'available';
$cards = App\Card::with(['statuses' => function($q) use($filter) {
$q->where('status_type', $filter)->latest()->take(1);
}])->get();
Hope this helps to guide you in the right direction!
Firstly since you have a hasMany relationship, the naming should be plural.
public function Statuses() {
Defining an Accessor can help you on your status problem. In your Card.php model define it.
public function getStatusAttribute()
{
return $this->statuses->first();
}
Using the appends property on your Card.php model, to tell which properties should be serialized.
protected $appends = ['status'];
This will result in your model looking like so, when it is transformed to JSON.
{
"card_type": "tag",
"status": {
"id_card": 1,
"status_date": "2020-02-02",
"status_company": "Company C",
"status_user": "Third User"
}
}
If you are using it, in a Blade or PHP -context you can access like so.
$card->status; //your first status
For your query needs a simply where() clause combined with joining the table. For performance it would be smart to eager load statuses as you will access the first status, with() can be used for this.
Card::leftJoin('statuses', 'cards.id_card', 'statuses.id_card')
->where('statuses.status_type', 'available')
->select('cards.*')
->with('statuses')
->get();
Your naming of the columns is inconsistent with the Laravel naming convention and your data structure seems a little bit off, but this solves your problem, i would consider to rethink it.

How to create column for selected parameter?

I have this query that pulls results based on the selected LOV parameter: nvl(:Role, role))
SELECT role,subject
FROM HS_SUBJECT_INCIDENTS
WHERE entitlement not in(select entitlement from HS_SUBJECT_INCIDENTS where role in nvl(:Role, role))
AND subject in (select subject from HS_SUBJECT_INCIDENTS where role in nvl(:Role, role))
So if the user selected 'Finance' for the parameter value, the results now show:
| Role | Subject |
------------------------
| Marketing | Business |
| Marketing | Business |
| Analytics | Business |
I want the results to show like this:
| Role | Subject | SelectedParameter |
--------------------------------------------
| Marketing | Business | Finance |
| Marketing | Business | Finance |
| Analytics | Business | Finance |
What do I have to put in the select statement to include a column for the parameter value that was selected?
Just select it:
SELECT role, subject, :Role as SelectedParameter
FROM . . .

Custom columns per specific column

I'm currently having a problem designing a table with custom columns,
my scenario is that I have this following tables:
User Table
--------------------------------------------------
| Name | House |
--------------------------------------------------
| UserNameA | 1 |
--------------------------------------------------
House Table
--------------------------------------------------
| ID | Name |
--------------------------------------------------
| 1 | House A |
--------------------------------------------------
| 2 | House B |
--------------------------------------------------
This is my current design, how can I add a table that when I choose house_id=1
UserNameA user will have custom_tag, custom_address
then when I choose house_id=2
UserNameA user will have custom_country, custom_phone_number
As per output per JSON and Table it would be like
Scenario A in Table output
--------------------------------------------------------------
| Name | House | Custom Tag | Custom Address
--------------------------------------------------------------
| UserNameA | 1 | Tag A | Miami Beach, Florida
--------------------------------------------------------------
Scenario B in JSON output
{
"name": "UserNameA:
"house: {
"custom_country": "turkey",
"custom_phone_number": "+12345"
}
}
You seem to want an entity-attribute-value model (EAV). You would have a table that looks like:
house_id attribute value
1 tag ...
1 address ...
2 country ...
2 phone_number ...