How to solve Laravel union queries with different number of columns - laravel

I have two tables contact_us and upload_new_car.
contact_us table contains columns:
id
name
email
phone
message
created_at
updated_at
upload_new_car contains columns:
id
name
phone_number
car_name
car_price
location
car_model_year
car_model
variant
driven
fuel
transmission
city
no_of_owners
upload_1
upload_2
upload_3
upload_4
upload_5
created_at
updated_at
How can I get the UNION of these tables in Laravel? Please help

Not allowing to different size of columns is not laravel's businuess. It is a matter of SQL .You can follow [this link] for more info about UNION statements .
On the other hand for laravel you can use those syntax using union (We can benefit from selecting the same count of columns from each tables).
$first = DB::table('contact_us')
->select('name','phone');
$users = DB::table('users')
->select('name','phone_number as phone')
->union($first)
->get();
dd($users)

Related

In Laravel Eloquent, how do I reference primary query in subquery

I have a model User that has many Orders. Orders have many products, with the pivot table order-product. I don't want to preload and iterate through the orders if at all possible.
I need to return users where
signed_date === true on User
order_date on Order is after signed_date on User
order-product shows product hasn't been paid
I am failing on number 2.
In the following code, the first query within whereHas is wrong. I don't know how to reference the signed date of the user from within the where has. If I was iterating through users in a collection I could do something like ($query) use $user, but how do I do this without preloading all the users?
return User::whereNotNull('signed_date')
->whereHas('orders', function ($query) {
$query->where('order_date', '<=', 'user.signed_date');
$query->whereHas('products', function ($q) {
$q->where('paid', false);
});
})
->get(['id','fname','lname', 'title', 'signed_date']);
I would like to use eloquent if possible. If that is not possible, I would be happy for tips in solving this problem using the query builder/sql.
The Eloquent query builder has a special function called whereColumn('a', '<=', 'b') to compare columns instead of a column against a value. Using this function instead of a normal where() is necessary because of the way the query builder builds the actual query. You need to let the query builder know that you are going to pass a column name instead of a value for proper escaping and formatting of the query string.
Anyway, it seems you can also pass column names prefixed with a table name to the function, allowing you to compare columns across tables:
$query->whereColumn('orders.order_date', '<=', 'users.signed_date')
This works because you are using whereHas() in your query. Your query basically gets translated to:
SELECT id, fname, lname, title, signed_date
FROM users
WHERE signed_date NOT NULL
AND EXISTS (
SELECT 1
FROM orders
WHERE orders.order_date <= users.signed_date
AND EXISTS (
SELECT 1
FROM products
WHERE paid = 0
)
)
It might actually be not necessary at all to use the table name together with the column name in whereColumn(). But in case you'll ever add a column named the same on another table, the query might break - so IMHO it is good practice to use the table name in custom queries.
By the way, the reason this will not work together with with('relationship') is that this function results in an additional query and you obviously cannot compare columns across queries. Imagine the following:
Order::with('user')->take(5)->get();
It will be translated into the following:
SELECT *
FROM orders
LIMIT 5
SELECT *
FROM users
WHERE id IN (?, ?, ?, ?, ?)
where the five ? will be the user_ids of the orders. If the first query returns multiple rows with the same user_id, the amount of rows fetched from the users table gets reduced of course.
Note: All the queries are only examples. Might be that the query builder builds different queries based on the database type and/or escapes them differently (i.e. column names in backticks).

Join tables with with a condition and then aggregate columns

Given I have a simple join between two tables user and filled forms, filled forms has columns: value, sales and income.
Sales and income are boolean columns if any of them are set to true then I know which value are sales and which are income.
User::where('id', $id)
->leftJoin("filled_forms", function($join){
$join->on("user.form_id", "filled_forms.id")
->where("filled_forms.sales", true)
->where("filled_forms.income", true);
})->get();
Now all the fields that sales are set to true I want to
count(filled_forms.value) as number_of_sales and all the incomes
that are set to true I want to do sum(filled_forms.value) as income
I know that I could do something with DB::Raw maybe ?
You can create a SQL View for such requirements as it will provide you with a table with real time updated information.
http://beginner-sql-tutorial.com/sql-views.htm
Then you can follow standard laravel where condition to fetch data from the view.

Inner Join in laravel missing P

I needed to combine the two table product_price and trade_channels, when I use inner join,
the ID of product_price is remove.
Here is my code
DB::table('product_price')->where('product_id',$id)->where('action','customer_price')
->join('customers','product_price.action_id','=','customers.id')
->get();
A good practise is to select a column that you actually want to use no need of all columns.
Suppose in this case you require all column of product_price table and only customer id from customer_price table then you can do something like this:
DB::table('product_price')
->select(['product_price.*','customer_price.id AS customer_id'])
->where('product_price.product_id',$id)
->where('product_price.action','customer_price')
->join('customers','product_price.action_id','=','customers.id')
->get();
You can select any column but it's good to take alias of join table column in this case it is customer_price so it's not getting confusion if both table has same name column.
Good Luck
try
DB::table('product_price')
->select('*','product_price.id AS product_price_id')
->where('product_id',$id)
->where('action','customer_price')
->join('customers','product_price.action_id','=','customers.id')
->get();
the product_price id would be replace with customers id, so just print out the product_price id with other name.
hope it is help

Newest items and GROUP By with Eloquent

I have the following prices-table:
shop_id (int)
product_id (int)
price (float)
created (DateTime)
Every hour a cronjob checks the shops and inserts new entries (current prices) into these price-table.
Now I want to display the newest price for a product. I have to GROUP BY the shop_id because I only want one price per shop but I only want the newest entry (created).
Can I solve this with Eloquent Query-Builder or do I have to use raw SQL? Is it possible to pass the result of a raw SQL-query into a model if the columns are the same?
You can try it as:
Price::select('*', DB::raw('MAX(created_at) as max_created_at'))
->groupBy('shop_id')
->get()
Assuming model name is Price
Eloquent (purist) approach:
Price::orderBy('created', 'desc')->groupBy('shop_id')
->get('shop_id', 'price');
References:
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html#method_orderBy
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html#method_groupBy
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html#method_get
*untested though
Q: Is it possible to pass the result of a raw SQL-query into a model if the columns are the same?
A: you could pass it to Model's contructor - but it might need model's field to be fillable - or hydrate a model. Alternatively, just access it like an keyed-array, ie. $something[0]['price'] <-- assuming an array of prices with price column.
I solved the problem without QueryBuilder. Instead I use a raw SQL-statement and generating the models with the hydrateRaw()-function of the Model-class.
$prices = Price::hydrateRaw( 'SELECT p.*
FROM prices p
INNER JOIN (
SELECT shop_id, max(created_at) AS max_ca
FROM prices p1
GROUP BY shop_id
) m ON p.shop_id = m.shop_id AND p.created_at = m.max_ca');

Laravel mysqli connect 2 columns and change column name

I have 2 tables that I want to connect
table1:
id
name
table2_id
table_2:
id
name
table1 is connected with table2
When I try to select table1 and the connected row from table2 it works, but because the row names id and name are the same, it overwrites the values of table1.
How can I connect table1 with table2 and get a table1 with this rows in laravel:
id
name
table2_id
table2_name
Review the laravel documentation regarding relationships - If you set up your models as outlined here https://laravel.com/docs/5.3/eloquent-relationships you will be able to call the table2 like:
$result = Table1::find(1)->table2;
However to get the result you want you can use the ->select( function
DB::table('users')->select('name', 'email as user_email')->get();
https://laravel.com/docs/5.2/queries#selects
Something like this
public function scopetable1($query,$id){
return $query = DB::table('table1')
->select('table1.id as id','table1.name as name','table2.id as table2_id', 'table2.name as table2_name' )
->where('table1.id', '=', $id)
->leftJoin('table2', 'table1.table2_id', '=', 'table2.id')
->get();
}

Resources