I have a piece of script which is pulling through the desired figures fine. Now I need to multiply the figure given by another calculated field (I shall call field x, which is a case statement with 9 'When Statements') then multiply that by 0.74.
I can not get this to work at all... any ideas... script below
Case
when Left([dbo].[Table1].FIELD 1,3) = 'NEW' and [Field 2] = 'Live'
Then
(SELECT distinct[dbo].[Table2].[Field a]
FROM [MY_DATABASE].[dbo].[Table2]
right Join [dbo].[Table 3]
on ([dbo].[Table2].[Field b]=[dbo].[Table 3].[Field 1])
Where [dbo].[Table2].[Field c] =
(Select
[dbo].[Table 3].[Field1]
From [dbo].[Table 3]
Where [dbo].[Table 3].[Field4] = #parameter
and [Field5] = '7')
and [dbo].[Table2].[Field D]= #Parameter
and [dbo].[Table2].[Field E]= '07')
ELSE 0
END
As [Named Field]
One option here would be common table expressions.
I'd suggest wrapping your select in a cte, the selecting from it and performing any further calculations at the bottom level.
;with cte as (
your original select query
)
select *
, [named field] * [field x] as [calculated answer]
from cte
This saves you having to make the calculations over and over again. There are performance concerns around cte's but they can help in these situations. I'd test on your data and see how much of a hit you take.
Related
I have tried the following code.
SELECT (Team 1) OR ( Team 2) AS[Losser], Winner
FROM MatchesTbl
WHERE (WINNER NOT LIKE (Team 1))
I have attached an image of the table I am working with. I am working in Microsoft access.
I am still very new to programming and I am trying to do this for a school project.
If you use MS Access you can use the IIF function to get the first result
SELECT T.Team1, T.Team2, T.Winner, IIf([Team1]=[Winner],[Team2],[Team1]) AS Loser
FROM tblMatches AS T;
Please note that I modified your orignal table name and field names a little bit.
In MS Access you can save that query and based on the saved query (I saved it as qryLoser) you can get your second result
SELECT qryLoser.Loser, Count(qryLoser.Loser) AS CountOfLoser
FROM qryLoser
GROUP BY qryLoser.Loser;
Here is the original query -- as you an see I left some extra columns here (to make it clearer and you might want to use this for something else)?
SELECT Loser, COUNT(*)
FROM (
SELECT MatchID, [Match Date], Tournamer, [Team 1], [Team 2], Winner,
SWITCH([Team 1] = Winner,[Team 2],
[Team 2] = Winner,[Team 1],
true,'Unknown Loser') AS Loser
FROM MatchesTbl
) X
GROUP BY Loser
Here is the cleaned up answer:
SELECT Loser, COUNT(*)
FROM (
SELECT
SWITCH([Team 1] = Winner,[Team 2],
[Team 2] = Winner,[Team 1],
true,'Unknown Loser') AS Loser
FROM MatchesTbl
) X
GROUP BY Loser
also note, that the answer to your first question in the inner query and the answer to the second question is the outer query
I'd like to make a list based on whether a field in the original table is in two lists. My code is thus:
SELECT *
FROM ListofPlaces
WHERE Property = 'MODERATE'
and (HOMELAND in (
SELECT distinct HOMELAND
FROM PLANS
WHERE left(plans.code, 1) = '1')
or HOMELAND in (
'PlaceA'
, 'PlaceB'
, 'PlaceC'
, 'PlaceD'
, 'PlaceE'))
The list and the sub query will work fine individually, taking 00:00:01.43 for the sub query and 00:00:00.13 for the list, however they take around a min once combined.
I have tried using a left join, but this leads to a more significant reduction in performance.
The table 'PLANS' is a larger table of 4M+ rows, whilst list of places is less than 1000.
My question is whether I'm using the and/or operators efficiently, and if so, is there a more efficient way to run this query?
Try rewriting this using UNION:
SELECT *
FROM ListofPlaces
WHERE Property = 'MODERATE' AND
HOMELAND IN (SELECT HOMELAND
FROM PLANS
WHERE left(plans.code, 1) = '1'
)
UNION
SELECT *
FROM ListofPlaces
WHERE Property = 'MODERATE' AND
HOMELAND in ('PlaceA', 'PlaceB', 'PlaceC', 'PlaceD', 'PlaceE');
The optimizer can sometimes be confused by ORs. UNION may be needed here instead of UNION ALL if the two lists contain similar elements. Otherwise, if you know they are disjoint, use UNION ALL.
Why not join?
SELECT LoP.*
FROM ListofPlaces LoP
left join PLANS Pl
on LoP.HOMELAND = Pl.HOMELAND
WHERE Property = 'MODERATE'
and (left(plans.code, 1) = '1'
or LoP.HOMELAND in (
'PlaceA'
, 'PlaceB'
, 'PlaceC'
, 'PlaceD'
, 'PlaceE'))
I am having an issue with the following query returning results a bit too slow and I suspect I am missing something basic. My initial guess is the 'CASE' statement is taking too long to process its result on the underlying data. But it could be something in the derived tables as well.
The question is, how can I speed this up? Are there any glaring errors in the way I am pulling the data? Am I running into a sorting or looping issues somewhere? The query runs for about 40 seconds, which seems quite long. C# is my primary expertise, SQL is a work in progress.
Note I am not asking "write my code" or "fix my code". Just for a pointer in the right direction, I can't seem to figure out where the slow down occurs. Each derived table runs very quickly (less than a second) by themselves, the joins seem correct and the result set is returning exactly what I need. It's just too slow and I'm sure there are better SQL scripter's out there ;) Any tips would be greatly appreciated!
SELECT
hdr.taker
, hdr.order_no
, hdr.po_no as display_po
, cust.customer_name
, hdr.customer_id
, 'INCORRECT-LARGE ORDER' + CASE
WHEN (ext_price_calc >= 600.01 and ext_price_calc <= 800) and fee_price.unit_price <> round(ext_price_calc * -.01,2)
THEN '-1%: $' + cast(cast(ext_price_calc * -.01 as decimal(18,2)) as varchar(255))
WHEN ext_price_calc >= 800.01 and ext_price_calc <= 1000 and fee_price.unit_price <> round(ext_price_calc * -.02,2)
THEN '-2%: $' + cast(cast(ext_price_calc * -.02 as decimal(18,2)) as varchar(255))
WHEN ext_price_calc > 1000 and fee_price.unit_price <> round(ext_price_calc * -.03,2)
THEN '-3%: $' + cast(cast(ext_price_calc * -.03 as decimal(18,2)) as varchar(255))
ELSE
'OK'
END AS Status
FROM
(myDb_view_oe_hdr hdr
LEFT OUTER JOIN myDb_view_customer cust
ON hdr.customer_id = cust.customer_id)
LEFT OUTER JOIN wpd_view_sales_territory_by_customer territory
ON cust.customer_id = territory.customer_id
LEFT OUTER JOIN
(select
order_no,
SUM(ext_price_calc) as ext_price_calc
from
(select
hdr.order_no,
line.item_id,
(line.qty_ordered - isnull(qty_canceled,0)) * unit_price as ext_price_calc
from myDb_view_oe_hdr hdr
left outer join myDb_view_oe_line line
on hdr.order_no = line.order_no
where
line.delete_flag = 'N'
AND line.cancel_flag = 'N'
AND hdr.projected_order = 'N'
AND hdr.delete_flag = 'N'
AND hdr.cancel_flag = 'N'
AND line.item_id not in ('LARGE-ORDER-1%','LARGE-ORDER-2%', 'LARGE-ORDER-3%', 'FUEL','NET-FUEL', 'CONVENIENCE-FEE')) as line
group by order_no) as order_total
on hdr.order_no = order_total.order_no
LEFT OUTER JOIN
(select
order_no,
count(order_no) as convenience_count
from oe_line with (nolock)
left outer join inv_mast inv with (nolock)
on oe_line.inv_mast_uid = inv.inv_mast_uid
where inv.item_id in ('LARGE-ORDER-1%','LARGE-ORDER-2%', 'LARGE-ORDER-3%')
and oe_line.delete_flag <> 'Y'
group by order_no) as fee_count
on hdr.order_no = fee_count.order_no
INNER JOIN
(select
order_no,
unit_price
from oe_line line with (nolock)
where line.inv_mast_uid in (select inv_mast_uid from inv_mast with (nolock) where item_id in ('LARGE-ORDER-1%','LARGE-ORDER-2%', 'LARGE-ORDER-3%'))) as fee_price
ON fee_count.order_no = fee_price.order_no
WHERE
hdr.projected_order = 'N'
AND hdr.cancel_flag = 'N'
AND hdr.delete_flag = 'N'
AND hdr.completed = 'N'
AND territory.territory_id = ‘CUSTOMERTERRITORY’
AND ext_price_calc > 600.00
AND hdr.carrier_id <> '100004'
AND fee_count.convenience_count is not null
AND CASE
WHEN (ext_price_calc >= 600.01 and ext_price_calc <= 800) and fee_price.unit_price <> round(ext_price_calc * -.01,2)
THEN '-1%: $' + cast(cast(ext_price_calc * -.01 as decimal(18,2)) as varchar(255))
WHEN ext_price_calc >= 800.01 and ext_price_calc <= 1000 and fee_price.unit_price <> round(ext_price_calc * -.02,2)
THEN '-2%: $' + cast(cast(ext_price_calc * -.02 as decimal(18,2)) as varchar(255))
WHEN ext_price_calc > 1000 and fee_price.unit_price <> round(ext_price_calc * -.03,2)
THEN '-3%: $' + cast(cast(ext_price_calc * -.03 as decimal(18,2)) as varchar(255))
ELSE
'OK' END <> 'OK'
Just as a clue to the right direction for optimization:
When you do an OUTER JOIN to a query with calculated columns, you are guaranteeing not only a full table scan, but that those calculations must be performed against every row in the joined table. It appears that you can actually do your join to oe_line without the column calculations (i.e. by filtering ext_price_calc to a specific range).
You don't need to do most of the subqueries that are in your query--the master query can be recrafted to use regular table join syntax. Joins to subqueries containing subqueries presents a challenge to the SQL optimizer that it may not be able to meet. But by using regular joins, the optimizer has a much better chance at identifying more efficient query strategies.
You don't tag which SQL engine you're using. Every database has proprietary extensions that may allow for speedier or more efficient queries. It would be easier to provide useful feedback if you indicated whether you were using MySQL, SQL Server, Oracle, etc.
Regardless of the database you're using, reviewing the query plan is always a good place to start. This will tell you where most of the I/O and time in your query is being spent.
Just on general principle, make sure your statistics are up-to-date.
It's may not be solvable by any of us without the real stuff to test with.
IF that's the case and nobody else posts the answer, I can still help. Here is how to trouble shoot it.
(1) take joins and pieces out one by one.
(2) this will cause errors. Remove or fake the references to get rid of them.
(3) see how that works.
(4) Put items back before you try taking something else out
(5) keep track...
(6) also be aware where a removal of something might drastically reduce the result set.
You might find you're missing an index or some other smoking gun.
I was having the same problem and I was able to solve it by indexing one of the tables and setting a primary key.
I strongly suspect that the problem lies in the number of joins you're doing. A lot of databases do joins basically by systemically checking all possible combinations of the various tables as being valid - so if you're joinging table A and B on column C, and A looks like:
Name:C
Fred:1
Alice:2
Betty:3
While B looks like:
C:Pet
1:Alligator
2:Lion
3:T-Rex
When you do the join, it checks all 9 possibilities:
Fred:1:1:Alligator
Fred:1:2:Lion
Fred:1:3:T-Rex
Alice:2:1:Alligator
Alice:2:2:Lion
Alice:2:3:T-Rex
Betty:3:1:Alligator
Betty:3:2:Lion
Betty:3:3:T-Rex
And goes through and deletes the non-matching ones:
Fred:1:1:Alligator
Alice:2:2:Lion
Betty:3:3:T-Rex
... which means with three entries in each table, it creates nine temporary records, sorts through them all, and deletes six of them ... all before it actually sorts through the results for what you're after (so if you are looking for Betty's Pet, you only want one row on that final result).
... and you're doing how many joins and sub-queries?
First I'll try (with my bad English) to explain what I've got and what I need to have
I have got the list of Events by TimeLine.
Event is some discrete signal 1/0 that happens in some time and got some duration.
my event list is looking like
Rectime - start event time
Col - event name
ChangedDate - end event time
InitalValue - event message
Value - event state 1/0
And those events can call some Complex event if there are A1 event is 1 A2 is 0 or A5 is 1 in the same time -- Just for example
my complex events (incidents) structure is :
[ID] - just ID
[Name] - just Name
[SQL] - here is list of event names with logics alike ***(A1 AND NOT A2) OR A5***
[Message] - event message
I need do not miss any possible change so I when some event is happens I'm looking for complex events it could change , but to know if that changed complex events I need to know about other depends of this complex event, so next step is getting all the dependent events and their states 1/0. Here is my try :
With DependencedIncidents AS -- Get all dependenced Incidents from this Event
(
SELECT INC.[RecTime],INC.[SQL] AS [str] FROM
(
SELECT A.[RecTime] As [RecTime],X.[SQL] As [SQL] FROM [EventView] AS A
CROSS JOIN [Incident] AS X
WHERE
patindex('%' + A.[Col] + '%', X.[SQL]) > 0
) AS INC
)
, DependencedEvents AS -- Split SQL string to get dependeced Events for each dependeced Incident
(
select distinct word AS [Event] , [RecTime]
from
(
select v.number, t.[RecTime] As [RecTime],
substring(t.str+')',
v.number+1,
patindex('%[() ]%',
substring(t.str+')',
v.number+1,
1000))-1) word
from DependencedIncidents AS t
inner join master..spt_values v on v.type='P'
and v.number < len(t.str)
and (v.number=0 or substring(t.str,v.number,1) like '[() ]')
) x
where word not in ('','OR','AND')
)
, EventStates AS -- Dependeced events with their states 1/0
(
Select D.[RecTime], D.[Event], X.[Value]
From [DependencedEvents] AS D
LEFT JOIN [EventView] AS X
ON X.Col = D.[Event]
AND D.[Rectime] >= X.[Rectime]
AND D.[Rectime] <= X.[ChangedDate]
)
select * from EventStates
order by [RecTime]
And it works very very slow , I need a serious optimization if that possible.
The slowest ( 95% of time ) part is
LEFT JOIN [EventView] AS X
ON X.Col = D.[Event]
AND D.[Rectime] BETWEEN X.[Rectime] AND X.[ChangedDate]
maybe I'm doing something wrong here...
I just want to check Value of D.[Event] from EventView in this time D.[Rectime]...
eventview added by comments requests :
ALTER VIEW [dbo].[EventView] AS
(SELECT RecTime, ChangedDate, ( 'Alarm' + CAST(ID as nvarchar(MAX)) ) AS Col, InitialValue, Value FROM [dbo].[Changes]
WHERE InitialValue <> '')
UNION ALL
SELECT RecTime, ChangedDate, Col, InitialValue, Value FROM [dbo].[XDeltaIntervals]
UNION ALL
SELECT RecTime, ChangedDate, Col, InitialValue, Value FROM [dbo].[ActvXDeltaIntervals]
I think this should be about the same:
SELECT
ev.Rectime,
ev.Event,
ev2.Value
FROM EventView AS ev
INNER JOIN Incident i
ON PATINDEX('%' + ev.Col + '%', i.SQL) > 0
LEFT JOIN EventView ev2
ON ev.Col = ev2.Col AND ev.Rectime BETWEEN ev2.Rectime AND ev2.ChangedDate
The thing is, you are finding your complex events using event names, then you are extracting those very names from the complex events found, and finally you are using the extracted names in the last CTE to compare against themselves. So, it seemed to me that the extracting part was completely unnecessary.
And without it the resulting query turned out to be quite simple (in appearance at least).
Well one of the most basic concepts of relational data storage is to
store the data in a normalized way and
use the relational database to store the data, but do not parse/process it etc. Use the application layer to do that.
That should be the first thing you do and then you may move to the next level of optimizing the queries, joins, making indices etc.
I think the slowest part is originating from EventView definiton:
SELECT ... ( 'Alarm' + CAST(ID as nvarchar(MAX)) ) AS Col, ...
Joining with such calculated field causes nasty performance hit.
Can't you:
record (Col=)Alarm+ID directly to Changes table or
update Alarm+ID by trigger or
use indexed view for calculating Alarm+ID or
use temporary table for storing Alarm+ID or at least
not use nvarchar(MAX), but something like nvarchar(10) (if this changes query plan)
?
SQL newbie here. I have table setup as the following (my apologies for the poor formatting):
Cycle ID....UBCI....chemo_cycle....csf....rsn_no_csf
57.............18001...1......................N.......N 58.............18001...2......................N.......N59.............22002...1......................Y........null
I'd like to convert it into the following format:
UBCI....chemo_cycle1....chemo_cycle2....csf1....csf2....rsn_no_csf1....rsn_no_csf2 18001...1.........................2.........................N........N........N.....................N22002...1.........................null......................Y........null.....null..................null
There can be up to 26 chemo_cycles per UBCI. I tried some of the other suggestions, but wasn't familiar enough with SQL to work out some of the finer details. Again, apologies for the formatting. Any help would be appreciated.
Thank you!
-Omar
The only way I can see to do this conveniently in Access is with four queries. I do not think you can use crosstab queries as subqueries, so:
Query 1: cc
TRANSFORM First(TableQ.chemo_cycle) AS FirstOfchemo_cycle
SELECT TableQ.UBCI
FROM TableQ
GROUP BY TableQ.UBCI
PIVOT "CC " & [chemo_cycle];
Query 2: csf
TRANSFORM First(TableQ.csf) AS FirstOfcsf
SELECT TableQ.UBCI
FROM TableQ
GROUP BY TableQ.UBCI
PIVOT "csf " & [chemo_cycle];
Query 3: rsn
TRANSFORM First(TableQ.rsn_no_csf) AS FirstOfrsn_no_csf
SELECT TableQ.UBCI
FROM TableQ
GROUP BY TableQ.UBCI
PIVOT "rsn " & [chemo_cycle];
Final query:
The columns [cc 1] to [cc 26] will show in the design window, and can be added, here they are indicated by <...>
SELECT CC.UBCI,
CC.[CC 1],
CC.[CC 2],
<...>
csf.[csf 1],
csf.[csf 2],
<...>
rsn.[rsn 1],
rsn.[rsn 2]
<...>
FROM (CC INNER JOIN csf
ON CC.UBCI = csf.UBCI)
INNER JOIN rsn
ON csf.UBCI = rsn.UBCI;