create cdbcriteria for inner query in yii? - yii

I want to create my query with cdbcriteria in YII , with out using createCommand.
select count(*) count
from (select id,player_id,goals_scored,if(goals_scored>0,#counter:=#counter+1,#counter:=0) count from player_stats, (select #counter:=1) b
where player_id='1000099' and #counter>0 order by id desc) f
How can I create correct SQL query in YII syntax?

Why do you need CDbCriteria for this? You probably need the DAO and something like this:
$count = Yii::app()->db->createCommand("
select count(*) count
from (select id,player_id,goals_scored,if(goals_scored>0,#counter:=#counter+1,#counter:=0) count from player_stats, (select #counter:=1) b
where player_id='1000099' and #counter>0 order by id desc) f
")->queryScalar();
Usually CDbCriteria is used with ActiveRecord models but I don't see how it would be applicable in this particular case. If not, please show the full code sample.

Related

How to update a table using a CTE in Oracle

As an example in Sql server I can achieve this easily like so:
WITH cte_person AS
(
SELECT PersonalIdentificationNumber, PersonName
FROM Employee
)
UPDATE Person
SET Person.PersonName = cte.PersonName
FROM cte_person cte
WHERE Person.PersonalIdentificationNumber = cte.PersonalIdentificationNumber
But how do I achieve this in Oracle using a CTE specifically or is there no support for this? I have searched around and havn't found a satisfying answer. Most seem to wrap the CTE in an inline select statement.
Well, as you asked how to use a CTE in UPDATE, then:
update person p set
p.name = (with cte_person as
(select personalidentificationnumber, name
from employee
)
select c.name
from cte_person c
where c.personalidentificationnumber = p.personalidentificationnumber
)
where exists (select null
from employee e
where e.personalidentificationnumber = p.personalidentificationnumber
);
Though, merge is somewhat simpler as you don't have to additionally check which rows to update (see the exists clause in update example):
merge into person p
using (with cte_person as
(select personalidentificationnumber, name
from employee
)
select c.personalidentificationnumber,
c.name
from cte_person c
) x
on (p.personalidentificationnumber = x.personalidentificationnumber)
when matched then update set
p.name = x.name;
However, this can be simplified - see code Ankit posted (but - as I said - if you want to know how to use a CTE, then that's how).
Oracle does not allow for directly updating a CTE (unlike SQL Server, which allows it). If I understand your requirement correctly, you want to update the names in the Person table using the names from the Employee table, based on matching IDs. One way to do this in Oracle uses a correlated subquery.
UPDATE Person p
SET Name = (SELECT e.Name FROM Employee e
WHERE e.PersonalIdentificationNumber = p.PersonalIdentificationNumber);
You can use MERGE statement for this -
MERGE INTO Person p
USING Employee e
ON (p.PersonalIdentificationNumber = e.PersonalIdentificationNumber)
WHEN MATCHED THEN
UPDATE
SET p.Name = e.Name;

Get Limited Records For Sub Query Each Result

I am trying to query some data from SQL Server 2012 using sub query. I am trying to get first 3 records for each Id returned by Sub Query but I am not getting the idea how to do so for now I write this query:
Select * from Student Where TeacherId in (Select TeacherId from Teacher)
I am not sure if this is achievable by using such query or do I have to write a function or any thing else ?
Any Suggestions would be great and sorry for my bad explanation skills.
You should join the Teacher to Student table, and then use an analytic function to get the first there records for each teacher:
SELECT *
FROM
(
SELECT
s.*, t.TeacherId, t.TeacherName,
ROW_NUMBER() OVER (PARTITION BY t.TeacherId ORDER BY some_col) rn
FROM Teacher t
INNER JOIN Student s
ON t.TeacherId = s.TeacherId
) t
WHERE rn = 3;
I assume that there is a column in one of the two tables some_col which you want to use for ordering. It does not make much sense to speak of the first three records without also defining some ordering.
I guess you want the top 3 rows for each ids, not top 3 rows for entire result set
WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY t.TeacherId ORDER BY ?) Seq
FROM Student s
INNER JOIN Teacher t ON t.TeacherId = s.TeacherId
)
SELECT * FROM CTE
WHERE Seq between 1 AND 3
? placeholder requires column_name to generate the sequence_number to get the result with boundary of 1 to 3 .

SQL - extract column from subquery

I'm working on a database meant for auctions and I would like get the id of all the winning bids. The hard part is extracting it from a subquery that returns 2 columns: the id and the amount.
It looks something like this:
SELECT id FROM Bid WHERE id IN (Select ID,max(amount) FROM Bid group by bid.idAuction)
Can I somehow extract just one column from the subquery? Any other sugestions to do this task are helpfull too.
Thank you!
Your query is close, but you need a correlated subquery to make this work:
SELECT b.id
FROM Bid b
WHERE b.amount = (SELECT max(amount)
FROM Bid b2
WHERE b2.idAuction = b.idAuction
);
SELECT id, maxBid.MAmount, Bid.Amount
FROM Bid
INNER JOIN (Select ID,max(amount) mamount FROM Bid group by bid.idAuction) MaxBid
on MaxBid.ID = Bid.ID
RDBMS and SQL operate most effectively in SET based operations. So in this case we generate a set based on ID and max bid. We then join it back to the base set so that only the max bids are treturned.

Update using Distinct SUM

I have found a few good resources that show I should be able to merge a select query with an update, but I just can't get my head around of the correct formatting.
I have a select statement that is getting info for me, and I want to pretty much use those results to Update an account table that matches the accountID in the select query.
Here is the select statement:
SELECT DISTINCT SUM(b.workers)*tt.mealTax as MealCost,b.townID,b.accountID
FROM buildings AS b
INNER JOIN town_tax AS tt ON tt.townID = b.townID
GROUP BY b.townID,b.accountID
So in short I want the above query to be merged with:
UPDATE accounts AS a
SET a.wealth = a.wealth - MealCost
Where MealCost is the result from the select query. I am sure there is a way to put this into one, I just haven't quite been able to connect the dots to get it to run consistently without separating into two queries.
First, you don't need the distinct when you have a group by.
Second, how do you intend to link the two results? The SELECT query is returning multiple rows per account (one for each town). Presumably, the accounts table has only one row. Let's say that you wanted the average MealCost for the update.
The select query to get this is:
SELECT accountID, avg(MealCost) as avg_Mealcost
FROM (SELECT SUM(b.workers)*tt.mealTax as MealCost, b.townID, b.accountID
FROM buildings AS b INNER JOIN
town_tax AS tt
ON tt.townID = b.townID
GROUP BY b.townID,b.accountID
) a
GROUP BY accountID
Now, to put this into an update, you can use syntax like the following:
UPDATE accounts
set accounts.wealth = accounts.wealth + asum.avg_mealcost
from (SELECT accountID, avg(MealCost) as avg_Mealcost
FROM (SELECT SUM(b.workers)*tt.mealTax as MealCost, b.townID, b.accountID
FROM buildings AS b INNER JOIN
town_tax AS tt
ON tt.townID = b.townID
GROUP BY b.townID,b.accountID
) a
GROUP BY accountID
) asum
where accounts.accountid = asum.accountid
This uses SQL Server syntax, which I believe is the same as for Oracle and most other databases. Mysql puts the "from" clause before the "set" and allows an alias on "update accounts".

Convert SQL-query with subselect in select section to HQL

I have trouble with converting native SQL query to HQL.
Query is something like follows:
select count(*)
, sum(select count(*) from employee e where e.company_id=c.id))
from company c where c.id = someID
First returned value is count of companies, second - amount of employees for specified company.
I.e. I have to get this two values for company with id=someID.
The trouble is hibernate doesn't support subselects in SELECT section, only in WHERE - by specification.
Actually I can:
1) use native query to run this through EntityManager
2) do the same dividing this "complex" query to two simpler SQL queries
But may be there are exist more convenient methods to realize initial query in HQL? - this is a question.
Thank you.
this might work:
select count(c.*) as count_companies
, c as count_emp
from company c
inner join
(
select company_id, count(*) as c
from employee
where employee.company_id = someID
group by company_id
) e
on e.company_id=c.id
group by c.id