SQL Query to Cdbcriteria - yii

I have a SQL query like this
SELECT *
FROM nu.tb_class t
WHERE NOT EXISTS (SELECT st_id FROM student_class s WHERE s.st_id = t.id)
I need this to put it Cdbcriteria can any tell me how to do this ?
(somehow I need to put this data to CGridView if there is any other way I like to know it)

You can use the NotInCondition in your Criteria
http://www.yiiframework.com/doc/api/1.1/CDbCriteria#addNotInCondition-detail
Note: that it takes an array, that means you have to select only the st_id column, and pass it to the addNotInCondition function ... the easy way to do this is some thing like:
$st_ids = CHtml::listData(StudentClass::model()->findAll($criteria)), 'column1', 'column2');
And for sure you can run it as sql query, then use the CArrayDataProvider
http://www.yiiframework.com/doc/guide/1.1/en/database.dao#executing-sql-statements
http://www.yiiframework.com/doc/api/1.1/CArrayDataProvider

You can convert that query to an equivalent LEFT JOIN query:
$classes = TbClass::model()->findAll(array(
'condition' => 's.st_id IS NULL',
'join' => 'LEFT JOIN student_class s ON t.id=s.st_id',
));
Notice that you can pass the properties of a CDbCriteria to findAll().

Related

sequelize update statement with joined dynamic table

I have an update query like below which contains a join statement which is not a defined association. What would be the best way to convert this query to sequelize. I have googled but could not find a proper way to do this. I do not want to choose sequelize.literal or sequlize.query unless there is no alternative, and if there is not, then what would be the correct way to achieve this
UPDATE employees as comm left join (
SELECT
totalamount,
username, paid FROM payments as total where
paid=0 and group by username
) as tot on comm.username=tot.username
SET comm.paid = 1, comm.paidDate = NOW(), comm.paidBy = ?
where comm.username= ?
and comm.paid=0 and tot.totalamount = ?;

Yii: Executing the where condition before joining

I'm currently having a problem with my query
TableA::find()
->select('*')
->joinWith(['TableB'])
->joinWith(['TableC'])
->joinWith(['TableD'])
->where([TableA.attribute1=1 or TableA.attribute2=1])
->andWhere([(further possible conditions on the other Tables)])
->all()
The usual execution order for SQL Queries is From (with joins) and then where.
Is there a way to execute the first where condition before the joins, to reduce the amount of joined lines? Something like
TableA::find()
->where([TableA.attribute1=1 or TableA.attribute2=1])
->select('*')
->joinWith(['TableB'])
->joinWith(['TableC'])
->joinWith(['TableD'])
->andWhere([(further possible conditions on the other Tables)])
->all()
You can modify the condition that is used for joining the tables.
In SQL it would look like this:
SELECT
*
FROM
`tableA`
JOIN `tableB` ON (
`tableA`.`FK` = `tableB`.`PK`
AND `tableA`.`attr1` = 'someValue'
)
JOIN tableC ON (`tableB`.`FK` = `tableC`.`PK`)
To do that in Yii you can use ActiveQuery::onCondition() method. If you want to apply this condition only for this one query you can use callback in joinWith() method to modify the query used for join.
$query = TableA::find()
->joinWith([
'tableB' => function(\yii\db\ActiveQuery $query) {
$query->onCondition(['tableA.attr1' => 'someValue']);
}
])
//... the rest of query
Other option would be using a subquery in FROM part of sql query like this:
SELECT
*
FROM
(
SELECT
*
FROM
`tableA`
WHERE
`attr1` = 'someValue'
) AS `tableA`
JOIN `tableB` ON (`tableA`.`FK` = `tableB`.`PK`)
In yii:
$subQuery = TableA::find()
->select('*')
->where(['attr1' => 'someValue']);
$query = TableA::find()
->select('*')
->from(['tableA' => $subQuery])
->joinWith('tableB')
// ... the rest of query
The main weakness of this approach is that temporary table from your subquery won't have any indexes so the join and other conditions will be slower. It might still be worth to use this approach if the tableA has a lot of rows and the condition you want to apply before join will reduce the number of rows significantly.
Well, I think that's the best way at all. But if you don't print data from relation TableB or TabelC (you just get them only about where condition), you can set the relation like that:
TableA::find()
->joinWith('TableB', false) //dont load data from this relational table
->joinWith('TableC', false) //dont load data from this relational table
->joinWith(['TableD']) //load data from this relational table
->where([TableA.attribute1=1 or TableA.attribute2=1])
->andWhere([(further possible conditions on the other Tables)])
->all()

Search condition in where clause postgres

I am new to postgres, can anyone help me understand the role of ? in the where clause?
Select * from tablename1 as a
join tablename2 as e
on a.column1 = ? and a.id = e.id
and e.range between ? and ?;
These look like place holders for parameters that you need to assign in code outside of a SQL editor. The statement probably gets compiled by Postgres and you could call it many times with different sets of parameters.
? just represents that you should place appropriate id in a.colum1=? and two values after between clause if you want to get date in some range.

How to write a Linq statement in SQL?

I'm fairly new to using Linq in C# and I just want to know how a normal SQL statement will look like when compared to a Linq query?
I have this statement:
var query =
from b in db.Employee.Include(o => o.Position)
where b.Position.Position_Desc == "Junior" && b.Employee_ID == 5
select b;
So my actual question is how will this statement look if I were to write it in SQL?
query.ToString() should return the SQL.
Or you can use LinqPad
If there is a relation between Employees and Positions tables with foreign key say Employees.PositionId -> Positions.Id. Then you can use LEFT JOIN to write a similar SQL query:
SELECT Employees.*,
Positions.*
FROM Employees
LEFT JOIN Positions ON Employees.PositionId = Positions.Id
WHERE Positions.Position_Desc = 'Junior'
AND Employees.Employee_ID = 5
You can check your query in debug mode (see attach image)

Rails ActiveRecord where or clause

I'm looking to write an ActiveRecord query and this is what I have below. Unfortunately you can't use OR like this. What's the best way to execute? category_ids is an array of integers.
.where(:"categories.id" => category_ids).or.where(:"category_relationships.category_id" => category_ids)
One way is to revert to raw sql...
YourModel.where("categories.id IN ? OR category_relationships.category_id IN ?", category_ids, category_ids)
Keep the SQL out of it and use ARel, like this:
.where(Category.arel_table[:id].in(category_ids).
or(CategoryRelationship.arel_table[:category_id].in(category_ids))
Assuming you want to return Categories, you need to OUTER JOIN category_relationships and put a OR condition on the combined table.
Category.includes(:category_relationships).where("categories.id IN (?) OR category_relationships.category_id IN (?)",category_ids,category_ids )
This query is creating an outer join table by combining columns of categories and category_relationships. Unlike an inner join (e.g. Category.joins(:category_relationships)), outer join table would also have categories with no associated category_relationship. It would then apply the conditions in whereclause on the outer join table to return the matching records.
includes statement without conditions on the association usually makes two separate sql queries to retrieve the records and their association. However when used with conditions on the associated table, it would make a single query to create an outer join table and run conditions on the outer join table. This allows you to retrieve records with no association as well.
See this for a detailed explanation.
What you want to do is manually write the OR part of the query like this:
.where("category.id in (#{category_ids.join(',')}) OR category_relationships.category_id in (#{category_ids.join(',')})")