I have a query which joins tables from two different databases. It is already showing results but then I wanted to show only unique results because some results are redundant. So I added a GROUP BY to get only the unique results but an error appears.
This is my code:
public function search_results_accommodations($location,$from_date,$to_date,$bedroom,$guests)
{
$this->db->select('*, akzapier.bookings.id as BOOKING_ID, akzapier.properties.id as PROPERTY_ID, ci_alexandrohomes.assigned_property.ID as ASSIGNED_PROPERTY_ID, ci_alexandrohomes.listings.ID as LISTING_ID');
$this->db->from('akzapier.bookings');
$this->db->join('akzapier.properties', 'akzapier.properties.id=akzapier.bookings.property_id', 'inner');
$this->db->join('ci_alexandrohomes.assigned_property', 'ci_alexandrohomes.assigned_property.property_id=akzapier.properties.id', 'inner');
$this->db->join('ci_alexandrohomes.listings', 'ci_alexandrohomes.listings.ID=ci_alexandrohomes.assigned_property.listing_id');
$this->db->where('akzapier.bookings.check_in !=', $from_date);
$this->db->where('akzapier.bookings.check_out !=', $to_date);
$this->db->where('ci_alexandrohomes.listings.city', $location);
$this->db->where('ci_alexandrohomes.listings.bedrooms', $bedroom);
$this->db->where('ci_alexandrohomes.listings.guests', $guests);
$this->db->group_by('akzapier.properties.id', 'ASC')
$query = $this->db->get();
return $query->result();
}
The error doesn't show up in the page so I converted it to SQL to see the real deal:
SELECT * akzapier.bookings.id as BOOKING_ID, akzapier.properties.id as PROPERTY_ID, ci_alexandrohomes.assigned_property.ID as ASSIGNED_PROPERTY_ID, ci_alexandrohomes.listings.ID as LISTING_ID
FROM akzapier.bookings
INNER JOIN akzapier.properties ON akzapier.properties.id=akzapier.bookings.property_id
INNER JOIN ci_alexandrohomes.assigned_property ON ci_alexandrohomes.assigned_property.property_id=akzapier.properties.id
INNER JOIN ci_alexandrohomes.listings ON ci_alexandrohomes.listings.ID=ci_alexandrohomes.assigned_property.listing_id
WHERE akzapier.bookings.check_in != '2019-09-21'
AND akzapier.bookings.check_out != '2019-09-30'
AND ci_alexandrohomes.listings.city = ‘1’
AND ci_alexandrohomes.listings.bedrooms = '2'
AND ci_alexandrohomes.listings.guests = '4'
GROUP BY akzapier.bookings.property_id ASC
ERROR SAYS:
1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'akzapier.bookings.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
In general, when you use GROUP BY, your SELECT statement must contain either aggregates (such as MAX(...), COUNT(...), etc.) or the columns must appear in GROUP BY. You have selected all of the fields, non-aggregated, with the asterisk *. In this case, it's complaining about the field akzapier.bookings.id, which is neither aggregated, nor in your GROUP BY.
If you actually want unique values, try SELECT DISTINCT, which will drop duplicate rows from the result.
Related
I have an order table and an order_details table in my system.
Relationship between order table and order details table is one to many, means One order has many order details.
Now the problem is i am trying to filter the order with the quantity of items a that are stored in order_details table.
what i doing right know trying to access with whereHas
if ($request->has('quantity') && $request->quantity != null){
$query = $query->whereHas('orderDetails',function ($q) use ($request){
$q->whereRaw('SUM(Quantity) >= '.$request->quantity);
});
}
$orders = $query->orderBy('OrderID','desc')->get();
But it throws an error
General error: 1111 Invalid use of group function (SQL: select * from `orders` where `AddedToCart` = 0 and `PaymentSucceeded` = 1 and exists (select * from `order_details` where `orders`.`OrderID` = `order_details`.`OrderID` and SUM(Quantity) >= 12) order by `OrderID` desc)
I will be vary thankful if i get the solution
To be able to use sum function you need to group by data and as I see you are trying to group them by orderID.
An approach like this might help:
$ordersIDs = DB::table('orderDetails')
->groupBy('OrderID')
->havingRaw('SUM(Quantity)', '>=', 12)
->pluck('orderID')->toArray();
$orders = DB::table('orders')
->whereIn($ordersIDs)
->get();
The above code executes two SQL queries, you can mix them easily to make one.
Hope it helps.
I have the following 4 SQL tables:
studios
integer id
string name
integer last_movie_id
movies
integer id
integer studio_id
string type
actor_movie
integer movie_id
integer actor_id
actors
integer id
string name
I'm trying to build a query that gives me for a specific actor, the list of the studios he worked for, including the last movie of the studio (wether the actor played in it or not):
name of the studio
date of the last movie from this studio
type of the last movie from this studio
My code is the following (in ActorController):
$actor = \App\Actor::findOrFail($id);
$studios = \DB::table('actor_movie')
->leftjoin('movies', 'actor_movie.movie_id', '=', 'movies.id')
->leftjoin('studios', 'studios.id', '=', 'movies.studio_id')
->select(
'studios.name',
'studios.last_movie_date'
\DB::raw('(SELECT movies.type FROM movies WHERE movies.id = studios.last_movie_id') as type')
->where('actor_movie.actor_id', $actor->id)
->groupBy('studios.name', 'studios.last_movie_date', 'type')
->get();
But I have the following error:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column [...] this is incompatible with sql_mode=only_full_group_by
I don't want to set the sql_strict_mode to false in order to circumvent this error. I would like to understand what's wrong with my query. I tried using aggregation functions like "ANY_VALUE" but nothing worked out.
You have written the query wrongly - specifically
\DB::raw('(SELECT movies.type FROM movies WHERE movies.id = studios.last_movie_id') as type which is in select statement. This query gives you value(s) not COLUNM NAME which should be in select statement like select col1Name, col2Name, .... from .....
As you did not provide full table structures & relation(i.e-you mentioned studios.last_movie_date in query but not in question) it is very hard for anyone to give you correct query but the below should work fine -
$actor = \App\Actor::findOrFail($id);
$studios = \DB::table('actor_movie')
->leftjoin('movies', 'actor_movie.movie_id', '=', 'movies.id')
->leftjoin('studios', 'studios.id', '=', 'movies.studio_id')
->leftjoin('movies as mov2', 'studios.last_movie_id', '=', 'mov2.id')
->select(
'studios.name',
'studios.last_movie_date',
'mov2.type'
)
->where('actor_movie.actor_id', $actor->id)
->groupBy('studios.name', 'studios.last_movie_date', 'type')
->get();
For other queries I think you got the idea.
How would I do it -
create a migration for below query -
create view actors_studio as
select am.actor_id, mov.studio_id, std.name as studio_name, std.last_mov_id, mov2.type as last_mov_type
from actor_movie as am
left join movies as mov on am.movie_id = mov.id
left join studios as std on std.id = mov.studio_id
left join movies as mov2 on std.last_movie_id = mov2.id
group by actor_id, studio_id, studio_name, last_mov_id, last_mov_type
order by actor_id, studio_id;
Then run the migrate command and then create a model for view actors_studio i.e VwActorStudios and then a simple query
$studios = VwActorStudios::where('actor_id', $actor->id)->get();
Introduction
So the idea is that I have a players table, all we need to know about this table is that it has an id and username fields.
I also have a financials table, all we need to know about this table is that it references the players table through the player_id foreign key. It also has another two fields, staked and won.
A player can have many financials. So for example, a player could have 5 financials records associated with themselves.
The issue
I'm attempting to return a list of players which are sorted by their financial records. So for example, I'd like to retrieve the players who have made the most net revenue for the company. Here is a query I have written against Laravel's
Query Builder (Illuminate\Support\Facades\DB).
DB::table('financials AS f')
->select(['*', DB::raw('SUM(staked - (won)) AS net_revenue')])
->join('players AS p', function ($join) use ($param) {
$join->on('f.player_id', '=', 'p.id')
->where('p.id', 'like', '%' . $param . '%')
->orWhere('p.username', 'like', '%' . $param . '%');
})
->orderBy('net_revenue')
->groupBy(['f.id'])
->paginate($perPage);
The Error
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #9 of
SELECT list is not in GROUP BY clause and contains nonaggregated column
'master.p.id' which is not functionally dependent on columns in GROUP BY
clause; this is incompatible with sql_mode=only_full_group_by (SQL: select
*, SUM(staked - (won)) AS net_revenue from `financials` as `f` inner join
`players` as `p` on `f`.`player_id` = `p`.`id` and `p`.`id` like %% or
`p`.`username` like %% group by `f`.`id` order by `net_revenue` asc limit 15
offset 0)
Could someone please point me in the right direction to fixing this issue? I'd greatly appreciate it.
EDIT (08/06/2017):
$query = DB::table('financials AS f1')
->select(['f1.id', 'f1.plays', 'f1.game_id', 'f1.staked', 'f1.won', 'f1.player_id', 'f1.date', 'f1.type', DB::raw('SUM(f1.staked - (f1.won)) AS net_revenue')])
->leftJoin('financials AS f2', 'f1.player_id', '=', 'f2.player_id')
->groupBy(['f1.id', 'f1.player_id', 'f1.game_id'])
->orderBy($orderBy)
->paginate($perPage);
So my query now looks like this, and it works, it generates the net_revenue for each record. However it returns me multiple records for the same player_id.
To elaborate, if I have two records for the same player, it calculates the net_revenue for both records and orders them from highest to lowest, however what I want is only a single record for the player containing the calculation of all net_revenue.
Change the order by as SUM(staked - (won)) instead of the field name.
Basically, I've got this coding convention that any primary key which is an ID, I will call the column name "id". So here comes my problem. I'm joining two tables and I'm getting the ID of the second table instead of the first table. I know if I use select "artists.id, ..." it will work, but I want to know if there's a fix with using "select *" which would be better for future expansion (new colums will come ...).
Here's my model:
$this->db->select('*');
$this->db->from('artists');
$this->db->join('categories', 'artists.category_id = categories.id');
$this->db->where('id', $id);
$this->db->limit(1);
With Print_R I can see I'm getting all columns (but only 1 id, which is from the categories table instead of artists table) without any table prefix.
You should qualify your columns with a table alias
$this->db->select('a.id as artist_id, c.id as category_id, a.column2,c.column3');
$this->db->from('artists a');
$this->db->join('categories c', 'a.category_id = c.categories.id');
$this->db->where('a.id', $id);
$this->db->limit(1);
If you want to continue using SELECT *
$this->db->select('a.*, c.*, a.id as artist_id, c.id as category_id');
$this->db->from('artists a');
$this->db->join('categories c', 'a.category_id = c.categories.id');
$this->db->where('a.id', $id);
$this->db->limit(1);
Keep in mind, that the LAST duplicate column will be returned. So, a.*,c.* will return c.id as id and c.*,a.* will return a.id as id.
I think to save you trouble and for the future, always use the table in front of the column name.
There is no logic here, when you look for * it means all fields, in Oracle for example you will get all fields with the table in front, i guess in MySQL it doesn't, but if i were you, i would not risk it.
my tables (structures, surface) have two Index-Rows, "planet_id" and "tile_id". I want to join them, but i get a SQL-Error: "Column 'planet_id' in where clause is ambiguous".
$this->db ->select('*')
->from('structures')
->join('surface', 'structures.planet_id=surface.planet_id AND structures.tile_id=surface.tile_id')
->where('planet_id', $p->planet_id);
$query = $this->db->get();
Leads to:
Error Number: 1052
Column 'planet_id' in where clause is ambiguous
SELECT * FROM (`structures`) JOIN `surface` ON `structures`.`planet_id`=`surface`.`planet_id` AND structures.tile_id=surface.tile_id WHERE `planet_id` = '13247'
Since you have planet_id in two tables, you'll need to choose which you're applying the where to.
So, try this:
$this->db->select('*')
->from('structures')
->join('surface', 'structures.planet_id=surface.planet_id AND structures.tile_id=surface.tile_id')
->where('structures.planet_id', $p->planet_id);
$query = $this->db->get();
It might seem silly, because your join requires both planet_id's to be the same, but the where doesn't know that, and needs specific instructions.