I'm still new to SQL and my question here is kinda long. Ok here it is...my task is to calculate the total downtime of machines situated in a particular location. Each machine has parent, children and grandchildren. For eg:
Location:A1
Machine no:A1-100, A1-100-01, A1-100-01-001, A1-200, A1-200-01
(A1-100-01, A1-100-01-001 belongs to A1-100) and (A1-200-01 belongs to A1-200)
This is my SQL query:
select machine_no, downtime from table_name where location='A1'
The output is:
machine_no downtime
A1-100-01 2
A1-100 1.5
A1-200 3
A1-100-01-001 0.5
A2-200-01 1.5
My question is how do I group the children and grandchildren to their parent and display the total downtime of that group? I'm sorry if the question is confusing but basically I want the output to be like this:
machine_no total_downtime
A1-100 4 (total of A1-100,A1-100-01,A1-100-01-001)
A1-200 4.5 (total of A1-200,A1-200-01)
Thank you.
try the following query:
SELECT machine_no, SUM(downtime) as total_downtime
FROM (
SELECT
SUBSTR(machine_no, 1,
CASE WHEN INSTR(machine_no, '-', 1, 2) = 0 THEN LENGTH(machine_no) ELSE INSTR(machine_no, '-', 1, 2)-1 END
) as machine_no, -- this will get the part of machine_no before the second '-' char
downtime
FROM MyTable
WHERE location='A1'
) InnerQuery
GROUP BY machine_no
output:
machine_no total_downtime
A1-100 4
A1-200 4.5
You don't actually need the inner query, but it's more readable then grouping by the SUBSTR(....) expression.
Play with it yourself on sql fiddle
You can use group by along with sum like :
select machine_no, sum(downtime) from table_name where location like 'A1-100%' group by machine_no;
Related
I have a simple manufacturing job card system that track parts and labor for an assigned job.
It consists of a JobHeader table that holds the Job Card number (JobHeader.JobNo), ID of the part being manufactured (JobHeader.RegNo) and quantity to be manufactured (JobHeader.RegNo).
There is a child table (JobLabour) that tracks all the times that have been worked on the job (JobLabour.WorkedTime)
I'm looking for a query that will return the average time taken to produce a part accross the last 5 job cards for that particular part.
The following query
SELECT TOP 5 JobHeader.RegNo, JobHeader.BOMQty, sum(JobLabour.WorkedTime) AS TotalTime FROM JobHeader INNER JOIN JobLabour ON JobHeader.JobNo=JobLabour.JobNo
WHERE JobHeader.RegNo='RM-BRU-0134'
GROUP BY JobHeader.BOMQty, JobHeader.JobNo, JobHeader.RegNo
will return this:
But what I'm looking for is a query that will return the average BOMQty and average totalTime. Something like this:
Is there a way to do this?
Your question explicitly mentions the "last five" but does not specify how that is determined. Presumably, you have some sort of date/time column in the data that defines this.
In SQL Server, you can use apply:
select jh.*, jl.*
from jobheader jh outer apply
(select top (5) avg(BOMQty) as avg_BOMQty, avg(totalTime) as avg_totalTime
from (select top (5) jl.*
from joblabour jl
where jl.regno = jh.regno
order by jl.<some datetime> -- however you determine the last five
) jl
) jl;
You can add a where clause to the outer query to filter on one or more particular jobs.
If I understand you correctly this will do the work
this will work for 1 RegNo='RM-BRU-0134' at a time
with topFive as (
SELECT TOP 5 JobHeader.RegNo, JobHeader.BOMQty, sum(JobLabour.WorkedTime) AS TotalTime
FROM JobHeader
INNER JOIN JobLabour ON JobHeader.JobNo = JobLabour.JobNo
WHERE JobHeader.RegNo = 'RM-BRU-0134'
GROUP BY JobHeader.BOMQty, JobHeader.JobNo, JobHeader.RegNo
)
select RegNo, avg(BOMQty) as BOMQty, avg(TotalTime) as TotalTime
from topFive
group by RegNo
Query is made in MS Access :
I show now a simplified example of my problem.
I have one table Members
Name/age/nickname
- Tom/12/wolf
- Chris/11/ranger
- Phil/14/H-man
- Chris/16/walker
- Chris/18/Mo
Goal: How many times a name occurs , but only count when the nickname had an "a" in it.
I needed 2 queries;
Step1:
SELECT Members.Name, Members.Age, Members.Nickname
FROM Members
WHERE (((Members.Nickname) Like "*A*"));
Step2:
SELECT Step1.Name, Count(Step1.Age) AS AantalVanAge
FROM Step1
GROUP BY Step1.Name;
Result
- Chris 2
- Phil 1
You can achieve this in a single query using:
select t.name, count(*) as AantalVanAge
from members t
where t.nickname like "*A*"
group by t.name
Use your 1st query as a subquery in the 2nd step:
SELECT t.Name, Count(t.Age) AS AantalVanAge
FROM (
SELECT Name, Age
FROM Members
WHERE Nickname Like "*A*"
) AS t
GROUP BY t.Name;
I work for a Logistics Company and we have to have a 7 digit Pro Number on each piece of freight that is in a pre-determined order. So we know there is gaps in the numbers, but is there any way I can Query the system and find out what ones are missing?
So show me all the numbers from 1000000 to 2000000 that do not exist in column name trace_number.
So as you can see below the sequence goes 1024397, 1024398, then 1051152 so I know there is a substantial gap of 26k pro numbers, but is there anyway to just query the gaps?
Select t.trace_number,
integer(trace_number) as number,
ISNUMERIC(trace_number) as check
from trace as t
left join tlorder as tl on t.detail_number = tl.detail_line_id
where left(t.trace_number,1) in ('0','1','2','3','4','5','6','7','8','9')
and date(pick_up_by) >= current_date - 1 years
and length(t.trace_number) = 7
and t.trace_type = '2'
and site_id in ('SITE5','SITE9','SITE10')
and ISNUMERIC(trace_number) = 'True'
order by 2
fetch first 10000 rows only
I'm not sure what your query has to do with the question, but you can identify gaps using lag()/lead(). The idea is:
select (trace_number + 1) as start_gap,
(next_tn - 1) as end_gap
from (select t.*,
lead(trace_number) order by (trace_number) as next_tn
from t
) t
where next_tn <> trace_number + 1;
This does not find them within a range. It just finds all gaps.
try Something like this (adapt the where condition, put into clause "on") :
with Range (nb) as (
values 1000000
union all
select nb+1 from Range
where nb<=2000000
)
select *
from range f1 left outer join trace f2
on f2.trace_number=f1.nb
and f2.trace_number between 1000000 and 2000000
where f2.trace_number is null
I am able to get count of column with most same values, e.g.
SELECT COUNT(*) AS Count, ProjectID
FROM Projects
GROUP BY ProjectID
ORDER BY Count DESC
So now I have table like this,
ProjectID ProjectUrl
1 http://www.CompanyA.com/Projects/123
2 http://www.CompanyB.com/Projects/124
3 http://www.CompanyA.com/Projects/125
4 http://www.CompanyB.com/Projects/126
5 http://www.CompanyA.com/Projects/127
Now Expected result without providing any parameter
ProjectUrl = http://www.CompanyA.com Count = 3
ProjectUrl = http://www.CompanyB.com Count = 2
Edit
Sorry I forgot to mention types of Urls I have in the table, Urls are quiet random though, but there are urls that are common. As we are creating project categories, so project category url can be,
https://spanish.CompanyAa2342.com/portal/projectA/projectTeamA/ProjectPersonA/Task/124
but for some projects there are no project team or so on, so it's bit random :?
I will need to query something more like generic.
What Url will have in common
http://ramdomLanguage.CompanyName.com/portal/RandomName.....
Please try:
select
Col,
COUNT(Col) Cnt
from(
select
SUBSTRING(ProjectUrl, 0, PATINDEX('%.com/%', ProjectUrl)+4) Col
from tbl
)x group by Col
SQL Fiddle Demo
Not sure of performance when dealing with a huge dataset, but this is a solution. I've tried to get a row for each portion of the URLs, delimited by /. Then do a quick aggregate at the end to bring up the counts of each individual part. Fiddle is here: http://www.sqlfiddle.com/#!3/742c4/12 (I've added one row for demo's sake - thanks, TechDo.)
WITH cteFSPositions
AS
(
SELECT ProjectID,
ProjectURL,
1 AS CharPos,
MAX(LEN(ProjectURL)) AS MaxLen,
CHARINDEX('/', ProjectURL) AS FSPos
FROM Projects
GROUP BY ProjectID,
ProjectURL
UNION ALL
SELECT ProjectID,
ProjectURL,
CharPos + 1,
MaxLen,
CHARINDEX('/', ProjectURL, CharPos + 1) AS FSPos
FROM cteFSPositions
WHERE CharPos <= MaxLen
),
cteProjectURLParts
AS
(
SELECT DISTINCT ProjectID,
LEFT(ProjectURL, FSPos) AS ProjectURLPart,
FSPos
FROM cteFSPositions
WHERE FSPos > 0
UNION ALL
SELECT ProjectID,
ProjectURL,
LEN(ProjectURL)
FROM Projects
),
cteFilteredProjectURLParts
AS
(
SELECT ProjectID,
ProjectURLPart
FROM cteProjectURLParts
WHERE ProjectURLPart NOT IN ('http:', 'http:/', 'http://', 'https:', 'https:/', 'https://')
)
SELECT ProjectURLPart,
COUNT(*) AS Instances
FROM cteFilteredProjectURLParts
GROUP BY ProjectURLPart
ORDER BY Instances DESC,
ProjectURLPart;
This produces (with the additional row I added in):
ProjectURLPart Instances
http://www.CompanyA.com/ 4
http://www.CompanyA.com/Projects/ 3
http://www.CompanyB.com/ 2
http://www.CompanyB.com/Projects/ 2
http://www.CompanyA.com/BlahblahBlah/ 1
http://www.CompanyA.com/BlahblahBlah/More1/ 1
http://www.CompanyA.com/BlahblahBlah/More1/More2 1
http://www.CompanyA.com/Projects/123 1
http://www.CompanyA.com/Projects/125 1
http://www.CompanyA.com/Projects/127 1
http://www.CompanyB.com/Projects/124 1
http://www.CompanyB.com/Projects/126 1
EDIT: Oops, original post had code of fiddle in progress. Have supplied the finalized code and updated fiddle link.
EDIT 2: Realized I was cutting off the end part of the URLS due to the way I was cutting the URLs up. For completeness' sake, I've added them back in to the final dataset. Updated fiddle as well.
I have the following table:
I am trying to create an SQL query that returns a table that returns three fields:
Year (ActionDate), Count of Built (actiontype = 12), Count of Lost (actiontype = a few different ones)
Bascially, ActionType is a lookup code. So, I'd get back something like:
YEAR CountofBuilt CountofLost
1905 30 18
1929 12 99
1940 60 1
etc....
I figured this would take two SELECT statements put together with a UNION.
I tried the following below but it only spits back two columns (year and countbuilt). My countLost field doesn't appear
My sql currently (MS Access):
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countBuilt
FROM ...
WHERE ((tblHist.ActionType)=12)
GROUP BY tblHist.ActionDate
UNION
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countLost
FROM ...
WHERE (((tblHist.ActionType)<>2) AND
((tblHist.ActionType)<>3))
GROUP BY tblHist.ActionDate;
Use:
SELECT h.actiondate,
SUM(IIF(h.actiontype = 12, 1, 0)) AS numBuilt,
SUM(IIF(h.actiontype NOT IN (2,3), 1, 0)) AS numLost
FROM tblHist h
GROUP BY h.actiondate
You should not use UNION for such queries. There are many ways to do what you want, for example
Updated to fit access syntax
SELECT tblHist.ActionDate,
COUNT(SWITCH(tblHist.ActionType = 12,1)) as countBuilt,
COUNT(SWITCH(tblHist.ActionType <>1 OR tblHist.ActionType <>2 OR ...,1)) as countLost
FROM ..
WHERE ....
GROUP BY tblHist.ActionDate