Issue with Order By with FOR XML in T-sql (The ORDER BY clause is invalid in views, inline functions, derived tables) - sql

select a.Hall, a.Title,
STUFF((SELECT ', ' + '[' + CONVERT(varchar(2),DATEPART(Hour, b.StartFilm))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.StartFilm))
+ ' ' + CONVERT(varchar(2),DATEPART(Hour, b.EndTime))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.EndTime))
+ ']'
FROM (select c.Name as Hall, b.Title,
Convert(time,a.StartFilmTime) as StartFilm,
Convert(time,a.EndFilmTime) as EndTime
from FilmSchedule a
left join Film b on a.FilmId = b.Id
left join Room c on a.RoomId = c.Id
where a.ApproveStatus = 1 and a.Status = 1
and CONVERT(date, a.StartFilmTime) = '05-06-2015'
) b
Where a.Hall = b.Hall and a.Title = b.Title
FOR XML PATH('')),1,1,'') As ShowTime
from (select c.Name as Hall, b.Title,
Convert(time,a.StartFilmTime) as StartFilm,
Convert(time,a.EndFilmTime) as EndTime
from FilmSchedule a
left join Film b on a.FilmId = b.Id
left join Room c on a.RoomId = c.Id
where a.ApproveStatus = 1 and a.Status = 1
and CONVERT(date, a.StartFilmTime) = '05-06-2015'
Order by a.StartFilmTime
) a
group by a.Hall, a.Title
I get the error:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
Help please! (I have used FOR XML?)

Although your query does use FOR XML (for the GROUP_CONCAT workaround), you are applying the order by outside of the derived table that uses FOR XML, hence the error.
Given that you aren't including start date directly in the final select (although you are composing it as part of the STUFF ShowTime column), you also can't ORDER BY StartFilm in the final GROUP BY either, as the column would otherwise need to be included in the GROUP BY or as an aggregated column.
What you can do is move the ORDER BY into the STUFF and then order by the derived column ShowTime (since your query only runs for one given day, and StartFilmTime is the first part of the STUFFED composed column).
At the same time, I would DRY up the repetition on the derived table with a CTE:
WITH cteFiltered AS
(select c.Name as Hall, b.Title,
Convert(time,a.StartFilmTime) as StartFilm,
Convert(time,a.EndFilmTime) as EndTime
from FilmSchedule a
left join Film b on a.FilmId = b.Id
left join Room c on a.RoomId = c.Id
where a.ApproveStatus = 1 and a.Status = 1
and CONVERT(date, a.StartFilmTime) = '05-06-2015'
)
select
a.Hall,
a.Title,
STUFF((SELECT ', ' + '[' + CONVERT(varchar(2),DATEPART(Hour, b.StartFilm))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.StartFilm))
+ ' ' + CONVERT(varchar(2),DATEPART(Hour, b.EndTime))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.EndTime))
+ ']'
FROM
cteFiltered b
Where
a.Hall = b.Hall and a.Title = b.Title
order by b.StartFilm -- ***
FOR XML PATH('')),1,1,'') As ShowTime
from
cteFiltered a
group by a.Hall, a.Title
order by ShowTime; -- *** Hour is first (assuming 24H format) and only one day

Related

SQL IN "Too many values"

I have a problem I want to get all of the DISTINCT CLIENTIDs in my LCMINV table in which the CLIENTID is in LAAPPL's CLIENTID and LACOBORW's COBORWID and also the APPLICATION STATUS is either 'PEN' OR 'REC'.
Here is my table:
++++++++++++++++++++++++++++++++++++++++++++
+ LAAPPL + LACOBORW + LCMINV +
++++++++++++++++++++++++++++++++++++++++++++
+ CLIENTID + APPLNO + CLIENTID +
+ APPLNO + COBORWID + +
+ STATUS + + +
++++++++++++++++++++++++++++++++++++++++++++
Here is my SQL Query I've done so far:
SELECT DISTINCT(CLIENTID)
FROM LCMINV
WHERE CLIENTID
IN (SELECT CLIENTID, COBORWID
FROM LAAPPL
LEFT OUTER JOIN LACOBORW ON LACOBORW.APPLNO = LAAPPL.APPLNO
WHERE STATUS = 'PEN' OR STATUS = 'REC')
Can it be done in one query or do I need separate queries? I tried my query above an I am getting an error "Too many values"
I would probably use a CTE to break the query up into smaller parts, and then use INNER JOINs to combine the tables. Since You query LAAPPL, I put both columns used into a single subquery, and then join on each column in the next CTE.
It would look something like this:
WITH CTE_LAAPPL AS
(
SELECT
CLIENTID
,APPLNO
FROM LAAPPL
WHERE STATUS IN ('PEN','REC')
)
,CLIENTIDs AS
(
SELECT DISTINCT
l.COBORWID AS CLIENTID
FROM CTE_LAAPPL c
INNER JOIN LACOBORW l ON l.APPLNO = c.APPLNO
UNION
SELECT DISTINCT
l.CLIENTID
FROM CTE_LAAPPL c
INNER JOIN LCMINV l ON l.CLIENTID = c.CLIENTID
)
SELECT
c.CLIENTID
,c.NAME
FROM LCCLIENT c
INNER JOIN CLIENTIDs i ON i.CLIENTID = c.CLIENTID
ORDER BY NAME
I think you just want:
SELECT DISTINCT i.CLIENTID
FROM LCMINV i
WHERE i.CLIENTID IN (SELECT a.CLIENTID
FROM LAAPPL a JOIN
LACOBORW c
ON c.APPLNO = a.APPLNO
WHERE a.STATUS IN ('PEN', 'REC')
);
I'm not really sure why you are joining in LACOBORW. You can probably remove that logic.
I would recommend left joins to get the data you need. Unfortunately, your question 3 does not seem to fit your model because your LCMINV table does not seem to have an id that matches to another table and I cannot understand where LCMINV.CLIENTID should be related to in another context. This works in MSSQL - cannot be sure about Oracle.
--this statement will give you all the names that have a status in the where clause
--you will receive NULL if there is no Co-BorrowerID
select
a.name
, b.applno
, b.status
, c.coborwid
from
lcclient a left join
laapl b on a.clientid = b.clientid left join
lacoborw c on b.applno = c.applno
where
b.status in ('PEN', 'REC')
order by
a.name

Filter based on where condition

I have a query where I am getting data for some tickets.Now I need to put a where condition to get data where timediffsecs <> 0.I am unable to get the correct place to put where conditon..
Below is my code .Please help
WITH CTE
AS
(
SELECT cr.ref_num as 'TicketNumber',
isnull(requestor.last_name,'') + ', ' + isnull(requestor.first_name,'') as 'Requestor'
,ISNULL(cnt.last_name, '') + ', ' + ISNULL(cnt.first_name,'') as 'Created By'
,isnull(aeu.last_name,'') + ', ' + isnull(aeu.first_name,'') as 'Affected End User',
isnull(logagent.last_name,'') + ', ' + isnull(logagent.first_name,'') as 'Reported By'
,dbo.ConvertUnixTime (cr.open_date) as 'Open Date'
,dbo.ConvertUnixTime (cr.last_mod_dt) as 'Last Modified Date'
,dbo.ConvertUnixTime (cr.resolve_date) as 'Resolve Date'
,dbo.ConvertUnixTime (cr.close_date) as 'Close Date'
,dbo.ConvertUnixTime (act.time_stamp) as 'systime',
cr.summary as 'Summary'
,convert(varchar(max),cr.[description]) as 'Description'
,act.[action_desc] as 'System Description'
,acttype.sym as 'Activity Type'
,act.time_spent as 'Time Spent',
ROW_NUMBER() OVER(PARTITION BY cr.ref_num ORDER BY dbo.ConvertUnixTime (act.time_stamp)) RN
-- ROW_NUMBER() OVER(ORDER BY dbo.ConvertUnixTime (act.time_stamp) ) RN
-- ROW_NUMBER generated based on ORDER BY Time DESC
-- You can also add case_id or any other column to generate
--ROW_NUMBER so that the time differences can be calculate
--based on other dimension.
from call_req cr with (nolock)
LEFT OUTER JOIN ca_contact requestor with (nolock) on cr.requested_by = requestor.Contact_uuid
LEFT OUTER JOIN ca_contact aeu with (nolock) on cr.customer = aeu.Contact_uuid
LEFT OUTER JOIN ca_contact logagent with (nolock) on cr.log_agent = logagent.Contact_uuid
INNER JOIN act_log act with (nolock) on cr.persid = act.call_req_id
INNER JOIN ca_contact cnt with (nolock) on act.analyst = cnt.contact_uuid
INNER JOIN act_type acttype with (nolock) on act.[type] = acttype.code
where cr.ref_num in ('23035883',
'23038276')
)
SELECT *,
CASE
WHEN A.RN = 3 THEN
DATEDIFF(
SECOND,
(SELECT systime FROM CTE WHERE RN = 2 AND TicketNumber= A.TicketNumber),
(SELECT systime FROM CTE WHERE RN = 3 AND TicketNumber= A.TicketNumber)
-- By setting RN = 3 and 2, I am calculating
-- Time differences between ROW 3 and 2
-- You can set it to any Row number as per your requirement
)
ELSE 0
END as timediffsecs
FROM CTE A
You just need to nest the current SELECT in a subquery:
WITH cte
....
SELECT *
FROM (
YourCurrentSelect
) q
WHERE q.timediffsecs <> 0

SQL Query Optimization -Slowing the Server

The system I maintain seems to slow down quite a bit every few days, and I assume it's from a bad query somewhere.
From what I can tell, I've narrowed the issue down to a page or two. Here's the query on the page that I think is causing the issue.
select a.s_purchase_order as order_id, a.order_type, a.nobackorder, a.order_note, a.note, a.rqst_dlvry_date, b.customer_name ,c.store_name,(c.store_name + ',' + isnull(c.address1 + ',', ' ') + isnull(c.city + ',', ' ') + isnull(c.state_cd+ ',', ' ') + isnull( c.zipcode, ' ')) as store_info, d.supplier_account
from VW_CustomerOrder a, Customer b, Store c, eligible_supplier d
where a.customer = c.customer
and a.store = c.store
and a.customer = b.customer
and c.customer *= d.customer
and c.store *= d.store
and a.supplier *= d.supplier
and a.purchase_order = #order_id
and a.customer = #customer_id
and a.store=#store_id
and a.supplier = #supplier_id
Is there something obvious there that would be very slow or cause the system to slow over time?
what about do some inner joins to solve this, check your base and see index and foreign keys for those table, this always is helpful in querys and performance
select
a.columun_a, b.column_a from table_a a
inner join table_b b on a.id = b.id
where
b.column_b = "some value"

SQL Error 1016 - Inner Joins

I'm trying to add inner joins to old SQL code to make it run more efficiently. But when I added them and tried to execute I get this error:
1016, Line 12 Outer join operators cannot be specified in a query containing joined tables
Here's the query:
select a.s_purchase_order as order_id,
a.order_type,
a.nobackorder,
a.order_note,
a.note,
a.rqst_dlvry_date,
b.customer_name ,
c.store_name,
(c.store_name + ',' + isnull(c.address1 + ',', ' ') + isnull(c.city + ',', ' ') + isnull(c.state_cd+ ',', ' ') + isnull( c.zipcode, ' ')) as store_info,
d.supplier_account
from VW_CustomerOrder a, Customer b, Store c, eligible_supplier d
where a.customer = c.customer
and a.store = c.store
and a.customer = b.customer
and c.customer *= d.customer
and c.store *= d.store
and a.supplier *= d.supplier
and a.purchase_order = #order_id
and a.customer = #customer_id
and a.store=#store_id
and a.supplier = #supplier_id
Any idea what's causing it? I'm guessing it has something to do with the isnull?
Did you try this? It replaces your commas between your tables with INNER JOIN and LEFT JOIN
select a.s_purchase_order as order_id,
a.order_type,
a.nobackorder,
a.order_note,
a.note,
a.rqst_dlvry_date,
b.customer_name ,
c.store_name,
(c.store_name + ',' + isnull(c.address1 + ',', ' ') + isnull(c.city + ',', ' ') + isnull(c.state_cd+ ',', ' ') + isnull( c.zipcode, ' ')) as store_info,
d.supplier_account
from VW_CustomerOrder a
INNER JOIN Customer b
ON a.customer = b.customer
INNER JOIN Store c
ON a.customer = c.customer
and a.store = c.store
LEFT JOIN eligible_supplier d
ON c.customer = d.customer
and c.store = d.store
and a.supplier = d.supplier
where a.purchase_order = #order_id
and a.customer = #customer_id
and a.store=#store_id
and a.supplier = #supplier_id
If you left your "*=" join operators in the code after you converted it to ANSI syntax, that would explain your error. Use = for all equality tests when using ANSI syntax -- the type of your JOIN should be explicit in the JOIN declaration itself (INNER, LEFT, RIGHT, etc.)

How can I use Sql to Order By This Statement?

How can I order the list 'widgets_spec by number of widgets?
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,widgets) + '<br> '
from dbo.spec_master m2
where m.p_c_id = m2.p_c_id and widgets is not null
for xml path(''), type).value('.[1]', 'nvarchar(max)'
) as widgets_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
Right now output looks like:
<li>10<br> <li>12<br> <li>15<br> <li>8<br>
When I want it to look like:
<li>8<br> <li>10<br> <li>12<br> <li>15<br>
Thanks for your help.
EDIT: I'm trying to order the internal select statement that concatenates the values.
You do not need both Distinct and Group By. You should use one or the other. In this case, I believe you have to use Group By for it to work.
Select m.p_c_id
, (
Select '<li>' + Cast( m2.num_of_lights As varchar(10)) + '<br /> '
From dbo.spec_master As m2
Where m.p_c_id = m2.p_c_id
And m2.num_of_lights Is Not Null
Group By m2.num_of_lights
Order By m2.num_of_lights
For Xml Path(''), type).value('.[1]', 'nvarchar(max)'
) As numLights_spec
From dbo.spec_master As m
Inner Join dbo.ProductVaration As pv
On pv.p_c_id = m.p_c_id
Inner Join dbo.Varation As v
On v.varation_id = pv.varation_type_id
Where v.varation_id = 4
Group by m.p_c_id
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,num_of_lights) + '<br> '
from dbo.spec_master m2
where m.p_c_id = m2.p_c_id and num_of_lights is not null
ORDER BY convert(varchar,num_of_lights)
) as numLights_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
) As SubA
Some of the other answers here won't work, since ordering by the now-varchar num_of_lights will put '8' after '15' as is happening now. You want to order the numLights numerically, which isn't going to happen with those html tags around them. You can add a subselect to your subselect so that you order them, then select them with the tags around them. Example (not tested):
SELECT * FROM (
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,num_of_lights) + '<br> '
from (select distinct p_c_id, num_of_lights from dbo.spec_master order by num_of_lights) m2
where m.p_c_id = m2.p_c_id and num_of_lights is not null
for xml path(''), type).value('.[1]', 'nvarchar(max)'
) as numLights_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
Personally, I'd just add the html tags in whatever back-end code is getting the result of the query.