I'm making a view. What i now have is:
CREATE VIEW [dbo].[vwEventDetails]
AS
SELECT
ISNULL(ROW_NUMBER() OVER (ORDER BY EventID), 999999999) AS Row,
STUFF(DetectorID, len(DetectorID), 1, '0') as SiteID,
DetectorID AS DetectorID,
StartedOn AS StartedOn,
EndedOn AS EndedON,
EventDescription AS EventDescription,
EventCategoryID AS EventCategoryID,
EventSeverityLevelID AS EventSeverityLevelID,
EventStatusID AS EventStatusID,
Processed AS Processed,
CASE WHEN EndedOn IS NOT NULL
THEN
DATEDIFF(SECOND, StartedOn, EndedOn)/ 3600.0
ELSE
DATEDIFF(SECOND, StartedOn, CURRENT_TIMESTAMP)/ 3600.0
END
AS Duration
FROM Event
GO
The result that i'm getting from this view is:
The result i'm getting is correct. However, i need 1 more value which is not in the Event table. And i dont know how to get this value.
The view is based on the Event table. which looks like this:
Now in this table there is a row called DetectorID.
DetectorID leads to the table: Detector:
In this table, you'll see a row named TrackID.
TrackID leads to the table Track:
In the table there is a row named TrackName.
This is the value that i want in the view.
Is there a way to achieve this?
So basically a short summary.
Is there a way to go from:
Event -> Detector -> Track
via a view which is based on Event?
Joining to other tables is a fairly standard thing in sql.
You can use an inner join to only return rows where there is a matching Detector and Track, or you could use left join when there may not be matching values in the corresponding tables.
Also, row_number() will not return null, no reason to wrap that in isnull().
--create view dbo.vwEventDetails as
select
row_number() over (order by e.EventId) as Row
, stuff(DetectorId, len(e.DetectorId), 1, '0') as SiteId
, e.DetectorId
, e.StartedO
, e.EndedOn
, e.EventDescription
, e.EventCategoryId
, e.EventSeverityLevelId
, e.EventStatusId
, e.Processed
, case when e.EndedOn is not null
then datediff(second, e.StartedOn, e.EndedOn)/ 3600.0
else datediff(second, e.StartedOn, current_timestamp)/ 3600.0
end as Duration
, t.TrackId
, t.FromName
, t.ToName
, t.TrackName
from Event e
inner join Detector d
on e.DetectorId = d.DetectorId
inner join Track t
on d.TrackId = t.TrackId
You can do it with two join statements:
...
FROM Event
JOIN Detector ON Event.DetectorID = Detector.DetectorID
JOIN Track ON Detector.DetectorID = Track.TrackID
Then add Track.TrackName to the end of the select fields
(you'll have to add Event. before your other fields where there are columns with the same names)
Related
Goal: Create a query to pull the closest cycle count event (Table C) for a product ID based on the inventory adjustments results sourced from another table (Table A).
All records from Table A will be used, but is not guaranteed to have a match in Table C.
The ID column will be present in both tables, but is not unique in either, so that pair of IDs and Timestamps together are needed for each table.
Current simplified SQL
SELECT
A.WHENOCCURRED,
A.LPID,
A.ITEM,
A.ADJQTY,
C.WHENOCCURRED,
C.LPID,
C.LOCATION,
C.ITEM,
C.QUANTITY,
C.ENTQUANTITY
FROM
A
LEFT JOIN
C
ON A.LPID = C.LPID
WHERE
A.facility = 'FACID'
AND A.WHENOCCURRED > '23-DEC-22'
AND A.ADJREASONABBREV = 'CYCLE COUNTS'
ORDER BY A.WHENOCCURRED DESC
;
This is currently pulling the first hit on C.WHENOCCURRED on the LPID matches. Want to see if there is a simpler JOIN solution before going in a direction that creates 2 temp tables based on WHENOCCURRED.
I have a functioning INDEX(MATCH(MIN()) solution in Excel but that requires exporting a couple system reports first and is extremely slow with X,XXX row tables.
If you are using Oracle 12 or later, you can use a LATERAL join and FETCH FIRST ROW ONLY:
SELECT A.WHENOCCURRED,
A.LPID,
A.ITEM,
A.ADJQTY,
C.WHENOCCURRED,
C.LPID,
C.LOCATION,
C.ITEM,
C.QUANTITY,
C.ENTQUANTITY
FROM A
LEFT OUTER JOIN LATERAL (
SELECT *
FROM C
WHERE A.LPID = C.LPID
AND A.whenoccurred <= c.whenoccurred
ORDER BY c.whenoccurred
FETCH FIRST ROW ONLY
) C
ON (1 = 1) -- The join condition is inside the lateral join
WHERE A.facility = 'FACID'
AND A.WHENOCCURRED > DATE '2022-12-23'
AND A.ADJREASONABBREV = 'CYCLE COUNTS'
ORDER BY A.WHENOCCURRED DESC;
I have a table full of event sequences where each event sequence has many unique events with a timestamp ts, a text field event_text, and a unique id event_id. I am querying the table looking for all event sequences which have an event_text that matches the search criteria, i.e. test% in the below case.
I am trying to first find each event where that text occurs and then for context find the event directly following by ts and directly preceding by ts the selected event. As you can see in the below example code, I am able to get the event directly following without too much issue, but how could I get both the event before, the selected event and the event after using the same query?
SELECT a.event_sequence_id,
a.event_id,
(ARRAY_AGG(ROW_TO_JSON((
SELECT t FROM (SELECT p.*) t)
) ORDER BY ts ASC))[1:2] AS event_sequence
FROM event_sequence_table a JOIN LATERAL (
SELECT event_sequence_id,
ts,
event_text,
event_id,
FROM event_sequence_table
WHERE event_sequence_id = a.event_sequence_id
AND ts >= a.ts
) p ON TRUE
WHERE event_text ILIKE 'test%'
GROUP BY a.event_sequence_id, a.event_id
Use the window functions lag() and lead(). Example:
select
to_json(lag) as previous,
to_json(a) as found,
to_json(lead) as next
from (
select
event_text,
lag(a) over w,
a,
lead(a) over w
from event_sequence_table a
window w as (partition by event_sequence_id order by ts)
) s
where event_text ilike 'test%';
I'm wondering if anybody can help me out with any or all of this code below. I've made it work, but it seems inefficient to me and is probably quite a bit slower than optimal.
Some basic background on the necessity of this code in the first place:
I have a table of shipping records that does not include the corresponding invoice number. I've looked all through the tables and I continue to do so. In fact, only this morning I discovered that if a packing slip has been generated that I can link the shipping table to the packing slip table via that packing slip ID and grab the invoice number from there. Absent that link, however, I'm forced to guess. In most instances, that's not terribly difficult, because the invoice table has number, line and release that can match up. But when there are multiple shipments for number, line and release (for instance, when a line is partially shipped) then there can be multiple answers, only one of which is correct. I am partially helped by the presence of a a column in the shipping table that states what the date sequence is for that number, line and release, but there are still circumstances where the process I use for "guessing" can be somewhat ambiguous.
What my procedure does is this. First, it creates a table of data that includes the invoice number if there was a pack slip to link it through.
Next, it dumps all of that data into a second table, this time using--only if the invoice was NULL in the first table--a "guess" about the invoice number based on partitioning all the shipping records by number, line, release, date sequence and date, and then comparing that to the same type of thing for the invoice table, and trying to line everything up by date.
Finally, it parses through that table and finds any last nulls and essentially matches them up with the first record of any invoice for that number, line and release.
Both guesses have added characters to show that they are, in fact, guesses.
IF OBJECT_ID('tempdb..#cosTAble') IS NOT NULL
DROP TABLE #cosTable
DECLARE #cosTable2 TABLE (
ID INT IDENTITY
,co_num CoNumType
,co_line CoLineType
,co_release CoReleaseType
,date_seq DateSeqType
,ship_date DateType
,inv_num NVARCHAR(14)
)
DECLARE
#co_num_ck CoNumType
,#co_line_ck CoLineType
,#co_release_ck CoReleaseType
DECLARE #Counter1 INT = 0
SELECT cos.co_num, cos.co_line, cos.co_release, cos.date_seq, cos.ship_date, cos.qty_invoiced, pck.inv_num
INTO #cosTable
FROM co_ship cos
LEFT JOIN pckitem pck
ON cos.pack_num = pck.pack_num
AND cos.co_num = pck.co_num
AND cos.co_line = pck.co_line
AND cos.co_release = pck.co_release
;WITH cos_Order
AS(
SELECT co_num, co_line, co_release, qty_invoiced, date_seq, ship_date, ROW_NUMBER () OVER (PARTITION BY co_num, co_line, co_release ORDER BY ship_date) AS cosrow
FROM co_ship
WHERE qty_invoiced > 0
),
invi_Order
AS(
SELECT inv_num, co_num, co_line, co_release, ROW_NUMBER () OVER (PARTITION BY co_num, co_line, co_release ORDER BY RecordDate) AS invirow
FROM inv_item
WHERE qty_invoiced > 0
),
cos_invi
AS(
SELECT cosO.*, inviO.inv_num
FROM cos_Order cosO
LEFT JOIN invi_Order inviO
ON cosO.co_num = inviO.co_num AND cosO.co_line = inviO.co_line AND cosO.cosrow = inviO.invirow)
INSERT INTO #cosTable2
SELECT cosT.co_num, cosT.co_line, cosT.co_release, cosT.date_seq, cosT.ship_date, COALESCE(cosT.inv_num,'*'+cosi.inv_num) AS inv_num
FROM #cosTable cosT
LEFT JOIN cos_invi cosi
ON cosT.co_num = cosi.co_num
AND cosT.co_line = cosi.co_line
AND cosT.co_release = cosi.co_release
AND cosT.date_seq = cosi.date_seq
AND cosT.ship_date = cosi.ship_date
WHILE #Counter1 < (SELECT MAX(ID) FROM #cosTable2) BEGIN
SET #Counter1 += 1
SET #co_num_ck = (SELECT co_num FROM #cosTable2 WHERE ID = #Counter1)
SET #co_line_ck = (SELECT co_line FROM #cosTable2 WHERE ID = #Counter1)
SET #co_release_ck = (SELECT co_release FROM #cosTable2 WHERE ID = #Counter1)
IF EXISTS (SELECT * FROM #cosTable2 WHERE ID = #Counter1 AND inv_num IS NULL)
UPDATE #cosTable2
SET inv_num = '^' + (SELECT TOP 1 inv_num FROM #cosTable2 WHERE
#co_num_ck = co_num AND
#co_line_ck = co_line AND
#co_release_ck = co_release)
WHERE ID = #Counter1 AND inv_num IS NULL
END
SELECT * FROM #cosTable2
ORDER BY co_num, co_line, co_release, date_seq, ship_date
You're in a bad spot - as #craig.white and #HLGEM suggest, you've inherited something without sufficient constraints to make the data correct or safe...and now you have to "synthesize" it. I get that guesses are the best you can do, and you can, at least make your guesses reasonable performance-wise.
After that, you should squeal loudly to get some time to fix the db - to apply the constraints needed to prevent further crapification of the data.
Performance-wise, the while loop is a disaster. You'd be better off replacing that whole mess with a single update statement...something like:
update c0
set inv_nbr = '^' + c1.inv_nbr
from
#cosTable2 c0
left outer join
(
select
co_num,
co_line,
co_release,
inv_nbr
from
#cosTable2
where
inv_nbr is not null
group by
co_num,
co_line,
co_release,
inv_nbr
) as c1
on
c0.co_num = c1.co_num and
c0.co_line = c1.co_line and
c0.co_release = c1.co_release
where
c0.inv_num is null
...which does the same thing the loop does, only in a single statement.
It seems to me that you are trying very hard to solve a problem that should not exist. What you describe is an unfortunately common situation where a process has grown organically without intent and specific direction as a business has grown which has made data extraction near impossible to automate. You very much need a set of policies and procedures- For (very crude and simple) example:
1: An Order must exist before a packing slip can be generated.
2: a packing slip must exist before an invoice can be generated.
3: an invoice is created using data from the packing slip and order (what was requested, what was picked, what do we bill)
-Again, this is a crude example just to illustrate the idea.
All of the data MUST be entered at the proper time or someone has not done their job.
It is not in the IT departments typical skillset to accurately and consistently provide management good data when such data does not exist.
I am trying to insert a value with a subquery including a column multiplication into a table. This works perfectly, however if I query the table, it only has 0 values. Does anybody know why?
My queries are:
create table user_payments
(payment_stream number(4));
insert into user_payments (payment_stream)
select ct.min_price*s.stream_min as payment_stream
from users u
, streaming s
, content_type ct
, contract c
, media_content mc
where u.user_ID = s.user_ID
and mc.media_content_ID = s.media_content_ID
and ct.content_type_ID = mc.content_type_ID
and u.user_ID = c.user_ID
and c.contract_name = 'Pay as you go';
If I query the select query individually, I get the expected outcome, however, once the rows are inserted into the table, all values are 0.
Thanks for your help!
try datatype numeric(18,2) in table var
I have 2 complex queries that are both subqueries in postgres, the results of which are:
q1_results = id , delta , metric_1
q2_results = id , delta , metric_2
i'd like to combine the results of the queries, so the outer query can access either:
results_a = id , delta , metric_1 , metric_2
results_b = id , delta , combined_metric
i can't figure out how to do this. online searches keep leading me to UNION , but that keeps the metrics in the same column. i need to keep them split.
It's not entirely clear what you're asking in the question and the comments, but it sounds like you might be looking for a full join with a bunch of coalesce statements, e.g.:
-- create view at your option, e.g.:
-- create view combined_query as
select coalesce(a.id, b.id) as id,
coalesce(a.delta, b.delta) as delta,
a.metric1 as metric1,
b.metric2 as metric2,
coalesce(a.metric1,0) + coalesce(b.metric2,0) as combined
from (...) as results_a a
full join (...) as results_b b on a.id = b.id -- and a.delta = b.delta maybe?