Adding to complex DQL Query - sql

Hello I have this query witch works fine
SELECT y,
CASE WHEN (v IS NULL) THEN 0 ELSE SUM(v.viewCount) END AS HIDDEN sumviewcount
FROM YTScraperBundle:YouTubeVideo y
LEFT JOIN y.allViews WITH v.firstFetch BETWEEN :fromDate AND :toDate
GROUP BY y ORDER BY sumviewcount DESC
This is the SQL that is generated by the DQL
SELECT y0_.id AS id0, y0_.video_id AS video_id1, y0_.name AS name2, y0_.type AS type3, y0_.link AS
link4, y0_.first_fetch AS first_fetch5, y0_.last_fetch AS last_fetch6, CASE WHEN (v1_.id IS NULL)
THEN 0 ELSE SUM(v1_.viewCount) END AS sclr7 FROM youtubevideo y0_ LEFT JOIN views v1_ ON y0_.id
v1_.youtubevideo_id AND (v1_.first_fetch BETWEEN ? AND ?) GROUP BY y0_.id, y0_.video_id, y0_.name,
y0_.type, y0_.link, y0_.first_fetch, y0_.last_fetch ORDER BY sclr7 DESC LIMIT 30 OFFSET 0
I need to add a upper LIKE clause, that sorts this first. The above query works fine, but it runs on all YouTubeVideo's y, if I want it to run on just some of the videos where name has a specifik LIKE value, I would add an AND clause after the LEFT JOIN.
But I dont know where to add it, if I add it after the:
BETWEEN :fromDate AND :toDate
Like this:
BETWEEN :fromDate AND :toDate AND y.name LIKE '%somevalue%'
The SQL renders like this:
LEFT JOIN views v1_ ON y0_.id
v1_.youtubevideo_id AND (v1_.first_fetch BETWEEN ? AND ? AND y.name LIKE '%somevalue%')
The clause I am adding should not be inside the between paranthesis. It shouldn't it be outside?
Anyway how can I get around the BETWEEN statment? can I make it a:
...MyComparison AND BETWEEN...
?

try below where clause
Where '2014-10-01'< Date_Column and '2014-11-01'>Date_column and name like '%abc%'

Related

Using SQL CASE Statement to replace Text with GROUP BY

I am Using SQL Server and i have the following Problem and i am hopping someone could help me.
I am getting this Error
Column 'TransactionsLine.Text' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I do not want to include Text in the GROUP BY Clause yes that makes the query run but the issue is there is other text in the field i do not want it grouping by i would just like to replace the Name with the Text for items matching the CASE
when i add Text to the group by i get this result.
43036 SPECIAL 73.0000
43036 SPECIAL 6.0000
Issue is exactly what the error says. You are selecting TransactionsLine.text which is not in the group by clause.
you probably want to put the case in your group by clause:
select StockItemCode as CODE,
(
case
when StockItems.Description like 'item%'
then TransactionsLine.text
else StockItems.Description
end
) as name,
SUM(ItemQuantity) as Sales
from Transactions
inner join TransactionsLine on Transactions.id = TransactionsLine.TransactionID
inner join StockItems on TransactionsLine.StockItemID = StockItems.id
where location = #location
and Department = 43
and Transactions.date between #FROM
and #TO
and TransactionTypeID in (3, 32)
group by StockItemCode,
case
when StockItems.Description like 'item%'
then TransactionsLine.text
else StockItems.Description
end

Case Statement as vals Outer Apply

I am trying to add a computed column to a table. Currently I have the following CASE statement building a calculated column in a SELECT statement,
--but I want to use this column to determine subsequent columns (sooo.. adding a computed column is somewhat a workaround to avoid complex CTE that i'm not sure i can figure out - let me know if CTE or functions is a better way to go)
--- I want the CASE statement to be a computed column in the table itself
SELECT top 1000
L.[MsgDate]
,C.[AlarmType]
,L.[Type]
,L.[UsrStr1]
,L.[UsrStr4]
,L.[UsrStr5]
,L.[UsrStr12]
,L.[UsrStr15]
,CASE
WHEN EXISTS
(
SELECT *
FROM Breinigsville.dbo.SCADA_SR S
WHERE S.SCADA_SR_TAG = L.UsrStr15 and
((L.[UsrStr4]='analog' and C.[AlarmType] like '%HH%') or (L.[UsrStr4]='status'))
)
THEN 1
ELSE 0
END AS [Safety]
FROM [Breinigsville].[dbo].[LMFW] L
full outer join [Breinigsville].[dbo].[_AcknowledgedAlarms] C
on
L.SeqNo=C.SeqNo2
WHERE (
L.[Type]='Ack' AND
L.UsrStr12 LIKE '%CCXOS%' AND
L.UsrStr12 NOT LIKE '%CCXOS5' AND
L.UsrStr12 NOT LIKE '%CCXOS6' AND
L.UsrStr12 NOT LIKE '%CCXOS9' AND
L.UsrStr12 NOT LIKE '%CCXOS12' AND
L.MsgDate>getdate()-1
)
order by L.SeqNo desc
Use outer apply:
FROM [Breinigsville].[dbo].[LMFW] L full outer join
[Breinigsville].[dbo].[_AcknowledgedAlarms] C
on L.SeqNo = C.SeqNo2 OUTER APPLY
(SELECT (CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END) as Safety
FROM Breinigsville.dbo.SCADA_SR S
WHERE S.SCADA_SR_TAG = L.UsrStr15 and
((L.[UsrStr4] = 'analog' and C.[AlarmType] like '%HH%') or
(L.[UsrStr4] = 'status')
)
) vals
Then you can use vals.Safety anywhere in the query.
Note: this version uses count(*). If performance is at all a concern, then you can get what you want using an additional subquery. I answered this way, because the structure of the query seems easier to follow.
Incidentally, you cannot easily put a subquery in as a computed column. You can do it, but it requires creating a user-defined function, and using that for the computed column. OUTER APPLY is definitely simpler, and you can even put this logic into a table-valued function or view.

SQL Oracle - Want to add another "like" condition to a case

I have the following query:
Select
Count(Distinct Case When Play.Uuid Like ('i~%') Then Tap.Player_Id End) As Tapjoy_Ios
From
Player_Tapjoy Tap
Inner Join
Player Play
On
Tap.Player_Id = Play.Player_Id
Where
Trunc(Tap.Create_Dtime) >= To_Date('2012-Jan-01','yyyy-mon-dd')
I want to add another like constrain so that the result comes out where play.uuid like ('i~%' or 'ti~%')..but that doesn't seem to work. How could I implement this?
You need two full LIKE clauses connected by a logical OR, each having both the left and right sides of the LIKE keyword (column on the left, string value on the right).
count(Distinct Case When (Play.Uuid Like 'i~%') OR (Play.Uuid LIKE 'ti~%') Then Tap.Player_Id End) As Tapjoy_Ios
You could also do this with a single REGEXP_LIKE, using the regular expressiong ^t?i~.+:
count(Distinct Case When REGEXP_LIKE(Play.Uuid, '^t?i~.+') Then Tap.Player_Id End) As Tapjoy_Ios
^ is the start of the string
t? is an optional t
i~ is literal
.+ is any remaining characters, equivalent to % in a regular LIKE.
You can just use an OR:
Select Count(Distinct Case When Play.Uuid Like ('i~%')
OR Play.Uuid Like ('ti~%')
Then Tap.Player_Id End) As Tapjoy_Ios
From Player_Tapjoy Tap
Inner Join Player Play
On Tap.Player_Id = Play.Player_Id
Where Trunc(Tap.Create_Dtime) >= To_Date('2012-Jan-01','yyyy-mon-dd')
While the answers are correct, you're applying the condition at the wrong level. You normally want to FILTER the data for better performance, although the LIKE clause here makes it less significant.
Select Count(Distinct Tap.Player_Id) As Tapjoy_Ios
From Player_Tapjoy Tap
Inner Join Player Play On Tap.Player_Id = Play.Player_Id
Where Tap.Create_Dtime >= To_Date('2012-Jan-01','yyyy-mon-dd')
And (Play.Uuid Like ('i~%') OR Play.Uuid Like ('ti~%'))
As written in the question, it was processing all rows and fizzing on the ones that don't match the LIKE pattern(s). You also don't want to run functions against columns, which doesn't allow indexes to be used - I have updated your date filter. You didn't really need the TRUNC.

Django: How do I explicitly make a query with a HAVING clause?

I need to execute some SQL that looks like this:
select approve_firm_id,approve_dt,approve_result
from main_approve
group by approve_firm_id
having MAX(approve_dt) and approve_result=0;
it runs (mysql-5.1),
but if I try in the Django model like this:
Approve.objects.annotate(max_dt=Max('approve_dt')).
filter(max_dt__gt=0).filter(approve_result=0).query
The query generated is this:
SELECT `main_approve`.`id`, `main_approve`.`approve_result`,
`main_approve`.`approve_dt`, `main_approve`.`approve_user_id`,
`main_approve`.`approve_firm_id`, `main_approve`.`exported_at`,
MAX(`main_approve`.`approve_dt`) AS `max_dt` FROM `main_approve`
WHERE (`main_approve`.`approve_result` = 0 )
GROUP BY `main_approve`.`id`
HAVING MAX(`main_approve`.`approve_dt`) > 0
ORDER BY NULL
I need the WHERE clause to be AFTER the GROUP BY clause.
Does the SQL even work? The having MAX(approve_dt) part certainly looks suspicious. Perhaps you mean this:
SELECT DISTINCT
main_approve.approve_firm_id,
main_approve.approve_dt,
main_approve.approve_result
FROM
main_approve
JOIN (
SELECT
approve_firm_id,
MAX(approve_dt) AS max_dt
FROM
main_approve
GROUP BY
approve_firm_id
) AS t
ON
main_approve.approve_firm_id = t.approve_firm_id
AND main_approve.approve_dt = t.max_dt
WHERE
main_approve.approve_result = 0;
It will be easier to construct the ORM expression after you know what exactly is the SQL going to be.

MySQL to PostgreSQL: GROUP BY issues

So I decided to try out PostgreSQL instead of MySQL but I am having some slight conversion problems. This was a query of mine that samples data from four tables and spit them out all in on result.
I am at a loss of how to convey this in PostgreSQL and specifically in Django but I am leaving that for another quesiton so bonus points if you can Django-fy it but no worries if you just pure SQL it.
SELECT links.id, links.created, links.url, links.title, user.username, category.title, SUM(votes.karma_delta) AS karma, SUM(IF(votes.user_id = 1, votes.karma_delta, 0)) AS user_vote
FROM links
LEFT OUTER JOIN `users` `user` ON (`links`.`user_id`=`user`.`id`)
LEFT OUTER JOIN `categories` `category` ON (`links`.`category_id`=`category`.`id`)
LEFT OUTER JOIN `votes` `votes` ON (`votes`.`link_id`=`links`.`id`)
WHERE (links.id = votes.link_id)
GROUP BY votes.link_id
ORDER BY (SUM(votes.karma_delta) - 1) / POW((TIMESTAMPDIFF(HOUR, links.created, NOW()) + 2), 1.5) DESC
LIMIT 20
The IF in the select was where my first troubles began. Seems it's an IF true/false THEN stuff ELSE other stuff END IF yet I can't get the syntax right. I tried to use Navicat's SQL builder but it constantly wanted me to place everything I had selected into the GROUP BY and that I think it all kinds of wrong.
What I am looking for in summary is to make this MySQL query work in PostreSQL. Thank you.
Current Progress
Just want to thank everybody for their help. This is what I have so far:
SELECT links_link.id, links_link.created, links_link.url, links_link.title, links_category.title, SUM(links_vote.karma_delta) AS karma, SUM(CASE WHEN links_vote.user_id = 1 THEN links_vote.karma_delta ELSE 0 END) AS user_vote
FROM links_link
LEFT OUTER JOIN auth_user ON (links_link.user_id = auth_user.id)
LEFT OUTER JOIN links_category ON (links_link.category_id = links_category.id)
LEFT OUTER JOIN links_vote ON (links_vote.link_id = links_link.id)
WHERE (links_link.id = links_vote.link_id)
GROUP BY links_link.id, links_link.created, links_link.url, links_link.title, links_category.title
ORDER BY links_link.created DESC
LIMIT 20
I had to make some table name changes and I am still working on my ORDER BY so till then we're just gonna cop out. Thanks again!
Have a look at this link GROUP BY
When GROUP BY is present, it is not
valid for the SELECT list expressions
to refer to ungrouped columns except
within aggregate functions, since
there would be more than one possible
value to return for an ungrouped
column.
You need to include all the select columns in the group by that are not part of the aggregate functions.
A few things:
Drop the backticks
Use a CASE statement instead of IF() CASE WHEN votes.use_id = 1 THEN votes.karma_delta ELSE 0 END
Change your timestampdiff to DATE_TRUNC('hour', now()) - DATE_TRUNC('hour', links.created) (you will need to then count the number of hours in the resulting interval. It would be much easier to compare timestamps)
Fix your GROUP BY and ORDER BY
Try to replace the IF with a case;
SUM(CASE WHEN votes.user_id = 1 THEN votes.karma_delta ELSE 0 END)
You also have to explicitly name every column or calculated column you use in the GROUP BY clause.