eloquent get latest raw in join clause - join

I use laravel 5.2 I'm trying to get latest intervention of each foreing key pmt_id like bellow:
$res = $this->model->with('typo', 'nro', 'ctr', 'cad', 'pm')
->join('a2t_intervention',function ($join) use ($salar){
$join->on('a2t_intervention.pmt_id','=','a2t_pmt.id');
$join->whereRaw('a2t_intervention.pmt_id = (select max(`pmt_id`) from a2t_intervention)');
$join->where('a2t_intervention.etat_intervention','like','nok');
$join->whereIN('a2t_intervention.id_equipe_stt',$salar);
});
but I get this ERROR :
Call to undefined method Illuminate\Database\Query\JoinClause::whereRaw()
I try other ways but nothig work for me.
for each pmt_id in the table intervention we have at least one record ,I'am looking for get the last intervention foreach single pmt_id before make join with table PMT.
how to select id from table intervention in latest pmt_id like bellow in sql query:
SELECT t.*
FROM ( SELECT pmt_id
, MAX(id) AS id
FROM a2t_intervention
WHERE etat_intervention = 'nok'
AND `id_equipe_stt` IN ('" . implode(',', $id_equipe_stt) . "')
GROUP
BY pmt_id ) AS m
INNER JOIN a2t_intervention AS t
ON t.pmt_id = m.pmt_id
AND t.id = m.id

Error is pretty self-explanatory - there is no whereRaw method. You could try to replace:
$join->whereRaw('a2t_intervention.pmt_id = (select max(`pmt_id`) from a2t_intervention)');
with
$join->where('a2t_intervention.pmt_id', '=', \DB::raw("(select max(`pmt_id`) from a2t_intervention)"));
In Later Laravel versions JoinClause extends Builder so whereRaw method is available but for Laravel 5.2 it isn't.

Related

wrong number of arguments (1 for 2..3) for Active Record postgresql query (Rails 4/postgresql 9.4) [duplicate]

Right now I am in the middle of migrating from SQLite to Postgresql and I came across this problem. The following prepared statement works with SQLite:
id = 5
st = ActiveRecord::Base.connection.raw_connection.prepare("DELETE FROM my_table WHERE id = ?")
st.execute(id)
st.close
Unfortunately it is not working with Postgresql - it throws an exception at line 2.
I was looking for solutions and came across this:
id = 5
require 'pg'
conn = PG::Connection.open(:dbname => 'my_db_development')
conn.prepare('statement1', 'DELETE FROM my_table WHERE id = $1')
conn.exec_prepared('statement1', [ id ])
This one fails at line 3. When I print the exception like this
rescue => ex
ex contains this
{"connection":{}}
Executing the SQL in a command line works. Any idea what I am doing wrong?
Thanks in advance!
If you want to use prepare like that then you'll need to make a couple changes:
The PostgreSQL driver wants to see numbered placeholders ($1, $2, ...) not question marks and you need to give your prepared statement a name:
ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
The calling sequence is prepare followed by exec_prepared:
connection = ActiveRecord::Base.connection.raw_connection
connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
st = connection.exec_prepared('some_name', [ id ])
The above approach works for me with ActiveRecord and PostgreSQL, your PG::Connection.open version should work if you're connecting properly.
Another way is to do the quoting yourself:
conn = ActiveRecord::Base.connection
conn.execute(%Q{
delete from my_table
where id = #{conn.quote(id)}
})
That's the sort of thing that ActiveRecord is usually doing behind your back.
Directly interacting with the database tends to be a bit of a mess with Rails since the Rails people don't think you should ever do it.
If you really are just trying to delete a row without interference, you could use delete:
delete()
[...]
The row is simply removed with an SQL DELETE statement on the record’s primary key, and no callbacks are executed.
So you can just say this:
MyTable.delete(id)
and you'll send a simple delete from my_tables where id = ... into the database.

Using combine and order together with Table Gateway in ZF2

When adding $select->order(...) to a previously combined Select in Zend Framework 2 the "order by" will only be added to the first Select statement.
SELECT `user`.*
FROM `user` WHERE `user_id` = :where1
ORDER BY `starttime_dt` ASC )
UNION
( SELECT `user`.*
FROM `user`
WHERE `user_id` != :subselect1where1 )
What I need is that the sorting will be applied to the full Select. A solution is already described here
https://github.com/zendframework/zf2/issues/5162#issuecomment-36294281
But this solution works with an SQL-Adapter.
How can I do that with a Table Gateway?
My code looks currently like this (resulting to the above statement)
$select = $this->tableGateway->getSql()->select();
$select2 = clone $select;
$select->where->equalTo('user_id', $user_id);
$select2->where->notEqualTo('user_id', $user_id);
$select->combine($select2);
$select->order('starttime_dt');
$resultSet = $this->tableGateway->selectWith($select);
You would do it with table gateway the same way it was illustrated in the link you provided.
Your code would look like
$select = $this->tableGateway->getSql()->select();
$select2 = clone $select;
$select->where->equalTo('user_id', $user_id);
$select2->where->notEqualTo('user_id', $user_id);
$select->combine($select2);
$combinedSelect = (new Zend\Db\Sql\Select)->from(['sub' => $select])->order('starttime_dt');
$statement = $this->sql->prepareStatementForSqlObject($combinedSelect);
$result = $statement->execute();
$resultSet = clone $this->resultSetPrototype;
$resultSet->initialize($result);
You wouldn't be able to use the TableGateway's selectWith method because it's going to check that the provided Select's table matches the TableGateway's table.

SCCM 2007 Report to check servers time zone

I need to create a SCCM 2007 report to check the time zone over a specific collection. I found something to do this, but is not working when i insert it in the Report SQL Statement.
select SMS_R_System.Name, SMS_R_System.SMSAssignedSites, SMS_R_System.IPAddresses, SMS_R_System.IPSubnets, SMS_R_System.OperatingSystemNameandVersion, SMS_R_System.ResourceDomainORWorkgroup, SMS_R_System.LastLogonUserDomain, SMS_R_System.LastLogonUserName, SMS_R_System.SMSUniqueIdentifier, SMS_R_System.ResourceId, SMS_R_System.ResourceType, SMS_R_System.NetbiosName, SMS_G_System_COMPUTER_SYSTEM.CurrentTimeZone from SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceID = SMS_R_System.ResourceId where SMS_G_System_COMPUTER_SYSTEM.CurrentTimeZone != -360 order by name
For a report you need to use the database views, see below for a quickly modified query which should do what you need:
select
v_R_System.Name0,
v_GS_COMPUTER_SYSTEM.CurrentTimeZone0
from v_R_System
inner join v_GS_COMPUTER_SYSTEM on v_GS_COMPUTER_SYSTEM.ResourceID = v_R_System.ResourceId
join v_FullCollectionMembership ON v_FullCollectionMembership.ResourceID = v_R_System.ResourceID
where
v_GS_COMPUTER_SYSTEM.CurrentTimeZone0 != -360
AND v_FullCollectionMembership.CollectionID = '<yourcollectionid>'
order by Name0
Just replace "<yourcollectionid>" with the id you want to query.

Selecting sum results from multiple tables in Rails

I am working in the Rails console. I would like to select the SUM of a same named column in two different tables.
Here is my ActiveRecord code:
Computer.joins(:services, :repairs)
.select("computers.id, SUM(services.cost) as SCOST, SUM(repairs.cost) as RCOST")
.group("computers.id")
This works well and returns the following correct SQL:
`SELECT computers.id, SUM(services.cost) as SCOST, SUM(repairs.cost) as RCOST
FROM "computers" INNER JOIN "services" ON "services"."computer_id" = "computers"."id"
INNER JOIN "repairs" ON "repairs"."computer_id" = "computers"."id"
GROUP BY computers.id `
But it gives the following result in the Rails console:
=> [#<Computer id: 36>, #<Computer id: 32>]
Shouldn't I be able to access my SUM values as well? I ran the above SQL query in postgres and it gave the desired output.
Any help would be appreciated.
Thanks.
The Rails console uses the inspect method to display the object content. This method doesn't display the values for the custom fields. You will be able to print the value of a custom attribute at the console by explicitly referring to it.
Computer.joins(:services, :repairs)
.select("computers.id, SUM(services.cost) as scost, SUM(repairs.cost) as rcost")
.group("computers.id").each do |c|
puts c.scost
puts c.rcost
end
Edit
Example based on comment:
Create a member variable in your controller:
#computers = Computer.joins(:services, :repairs)
.select("computers.id, SUM(services.cost) as scost, SUM(repairs.cost) as rcost")
.group("computers.id")
Iterate over the variable in your views
- #computers.each do |computer|
= computer.scost
= computer.rcost
Edit2
You need to use LEFT OUTER JOIN to get values for computers with missing repairs or services.
join_sql = "LEFT OUTER JOIN services ON services.computer_id = computers.id
LEFT OUTER JOIN repairs ON repairs.computer_id = computers.id"
sum_sql = "SUM(COALESCE(services.cost, 0)) as scost,
SUM(COALESCE(repairs.cost, 0)) as rcost"
#computers = Computer.joins(join_sql)
.select("computers.id, #{sum_sql}")
.group("computers.id")
try as follow,
#computer_list = Computer.joins(:services, :repairs).select("computers.id, SUM(services.cost) as SCOST, SUM(repairs.cost) as RCOST").group("computers.id")
#computer_list.last.SCOST

Copy an object with relations in which there is a Sortable object throws an Duplicate Entry error

In an old projet using symfony 1.4 There are an object Product linked to other objects such as Translation ProductPlatform ...
What I want to do is copy the Product object with all its relations.
Pretty simple with $product->copy(true) BUT
It doesn't copy the relations, so i need to do :
$this->loadReference('Translation');
$this->loadReference('ProductPlatforms');
foreach ($this->ProductPlatforms as $platform) {
$platform->loadReference('Translation');
}
$newProduct = $this->copy(true);
$newProduct->save();
return $newProduct;
The throwed error is this :
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-131' for key 'product_platform_position_sortable_idx'
What I don't understand is the following requests :
SELECT p.id AS p__id, p.position AS p__position FROM product_platform p
WHERE (p.product_id = 'EndNote (copie)') ORDER BY p.position desc LIMIT 1;
----
INSERT INTO product_platform (publish_configuration, product_id, platform_id, position)
VALUES ('1', '131', '1', '1')
And then, it reinsert, for another object, the same position :
INSERT INTO product_platform (publish_configuration, product_id, platform_id, position)
VALUES ('1', '131', '3', '1');
Why there is, instead of an ID, the Name of my object in the Where clause WHERE (p.product_id = 'EndNote (copie)'). I think this is the reason it tries to insert the same value.
Ok, it's a bug with the Sortable behaviour, we sent a PR :
https://github.com/bshaffer/csDoctrineActAsSortablePlugin/pull/25

Resources