I have the following select statement...
SELECT ROW_NUMBER() OVER(order by cola) as [id], cola
FROM Table1
That makes up my table of all values I'm wanting to insert as #var, right now it works but I have to specify #var each time...
SELECT #var AS [Cola], (
SELECT COUNT(*)
FROM vwTableA AS Z
WHERE Cola = COALESCE(#var,Cola)
AND NOT EXISTS (
SELECT *
FROM TableB
WHERE Colb = Z.Colb
)
) AS [NewCol1],
(
SELECT COUNT(*)
FROM vwTableB AS Y
INNER JOIN TableC AS C
ON Y.Colc = C.Colc
WHERE Y.Cola = #var
) AS [NewCol2],
(
SELECT COUNT(*)
FROM vwTableC AS X
INNER JOIN TableD AS D
ON X.Colc = D.Colc
WHERE X.Cola = #var
) AS [NewCol3]
So I'm wanting to run this second select through all the values of "cola" from the first Select/Table I showed, instead of having to specify the #var and it only return one row each time. How can I do this?
If you use a Common Table Expression CTE you can use it to join to your other statement
with var as
( SELECT ROW_NUMBER() OVER(order by cola) as [id], cola
FROM Table1)
SELECT var.id AS [Cola], (
SELECT COUNT(*)
FROM vwTableA AS Z
WHERE Cola = COALESCE(var.id,Cola)
AND NOT EXISTS (
SELECT *
FROM TableB
WHERE Colb = Z.Colb
)
) AS [NewCol1],
(
SELECT COUNT(*)
FROM vwTableB AS Y
INNER JOIN TableC AS C
ON Y.Colc = C.Colc
WHERE Y.Cola = var.id
) AS [NewCol2],
(
SELECT COUNT(*)
FROM vwTableC AS X
INNER JOIN TableD AS D
ON X.Colc = D.Colc
WHERE X.Cola = var.id
) AS [NewCol3]
FROM var
Related
I'm looking to add a column to display a count of all records where the drgpackid matches.
Essentially I want one line in the example provided and a count of how many records have that ID and meet the conditions of the query.
with C as (
select t1.*
from DrgPack t1 join
DrgPack t2
on t1.DrgID = t2.DrgID and t1.CentralMaintFieldMask <> t2.CentralMaintFieldMask
)
select *
from rxworkflowpack
where drgpackid in (select ID from c where CentralMaintFieldMask = 0)
There are a thousand ways to do this, like adding another CTE with the counts and joining to it
with C as (
select t1.*
from DrgPack t1 join
DrgPack t2
on t1.DrgID = t2.DrgID and t1.CentralMaintFieldMask <> t2.CentralMaintFieldMask
),
D as (
select drgpackid, count(*) from rxworkflowpack group by drgpackid)
select *
from rxworkflowpack left join D on rxworkflowpack.drgpackid = d.drgpackid
where drgpackid in (select ID from c where CentralMaintFieldMask = 0)
You can use window function like this:
with C as (
select t1.*
from DrgPack t1 join
DrgPack t2
on t1.DrgID = t2.DrgID and t1.CentralMaintFieldMask <> t2.CentralMaintFieldMask
)
select DISTINCT *, COUNT(*) OVER (PARTITION BY drgpackid) AS CountRecords from rxworkflowpack
where drgpackid in (select ID from c where CentralMaintFieldMask = 0)
You should use < to not double count
select t1.drgpackid, count(*) as cnt
from DrgPack t1
join DrgPack t2
on t1.DrgID = t2.DrgID
and t1.CentralMaintFieldMask < t2.CentralMaintFieldMask
join rxworkflowpack
on rx.ID = t1.drgpackid
and rx.CentralMaintFieldMask = 0
group by t1.drgpackid
So...
select COUNT(*) cnt from docDocument d
inner join tblAttachment a on d.AttachmentID = a.ID
where
a.ContainerID = 1
Returns 6673
select COUNT(*) from tblAttachment
where
ContainerID = 1
Returns 10372
select COUNT(*) cnt from docDocument d
right join tblAttachment a on d.AttachmentID = a.ID
where
a.ContainerID = 1
AND
d.ID IS NULL
Returns 3699 which makes sense as 10372 - 6673 = 3699
SELECT COUNT(*) FROM
(
select ID from tblAttachment a
where
a.ContainerID = 1
Except
(
SELECT AttachmentId from docDocument
)
) tst
Unsurprisingly returns 3699... However...
select COUNT(*) from tblAttachment a
where
a.ContainerID = 1 AND
a.ID NOT IN
(
SELECT d.AttachmentId from docDocument d
)
I was expecting this to return 3699 but surprisingly it's returning 0.
Can anyone explain these results?
If the subquery returns a null value, the NOT IN is no longer true, and no rows are returned.
Either aviod null values to be returned:
select COUNT(*) from tblAttachment a
where
a.ContainerID = 1 AND
a.ID NOT IN
(
SELECT d.AttachmentId from docDocument d WHERE d.AttachmentId IS NOT NULL
)
Or switch to the "null safe" NOT EXISTS:
select COUNT(*) from tblAttachment a
where
a.ContainerID = 1 AND
NOT EXISTS
(
SELECT * from docDocument d WHERE d.AttachmentId = a.ID
)
Your not in query return nulls value. So its displaying zero records.
This is the below scenario you are getting right now. Let's try to understand that and make the changes.
select *
into #tab1
from (select 'a' Name union all
select 'b'union all
select 'c'union all
select 'd'union all
select 'e') AS A
select *
into #tab2
from (select 'd' Name union all
select 'e' union all
select NULL) AS A
Not Exists
select Name
from #tab1
where not exists (select *
from #tab2
where #tab1.Name = #tab2.Name )
Left Join
select t1.Name
from #tab1 t1
left join #tab2 t2 on t1.Name = t2.Name
where t2.Name is null
Not in
select *
from #tab1
where Name not in (select Name from #tab2)
Note: whenever a Not in query returns NULL, the outer query returns blank data.
You must be having NULL values in docDocument table...That's why you are not getting anything.
Please try like this USE NOT EXISTS
select COUNT(*) from tblAttachment a
where
a.ContainerID = 1 AND
NOT EXISTS
(
SELECT d.AttachmentId from docDocument d
WHERE a.ID = d.ID
)
You can use EXCEPT operator.
select * into #tab1 from (
select 'a' Name union all
select 'b'union all
select 'c'union all
select 'd'union all
select 'e'
)AS A
select * into #tab2 from
(
select 'd' Name union all
select 'e' union all
select NULL
)AS A
SOLUTION
select Name from #tab1
EXCEPT
select * from #tab2
OUTPUT
Name
----
a
b
c
(3 rows affected)
In below code temp1 is used 2 times, so hive will be execute the select query in temp1 twice? or just once?
with temp1(
select distinct b as b, f, t1.id as id,
from
table1 t1
join
table2 t2 on (t1.id=t2.id)
),
agg_tbl as
(
select
max(abc) as maxabc,
tbl.t
from(
select
count(*) as cnt, b, f
from
temp1
group by
b, f
) tbl group by tbl.t
),
class_tbl as
(select
case
when bp = 1 then 'abc'
when bp = 2 then 'xyz'
end as class,
bp
from
( select
count(b) as bcount, bp
from
temp1
group by bp
)tbl
)
If that is the case, then using temporary tables will make sense.
Thanks.
How can I select like this? Can I create a User defined Aggregate Function
SELECT Max(A),(SELECT TOP 1 FROM TheGroup Where B=Max(A)) FROM MyTable
where MyTable as Shown Below
A B C
--------------
1 2 S
3 4 S
4 5 T
6 7 T
I want a Query Like this
SELECT MAX(A),(B Where A=Max(A)),C FROM MYTable GROUP BY C
I'm Expecting the result as below
MAX(A) Condition C
-----------------------
3 4 S
6 7 T
SELECT A,B,C FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY C ORDER BY A DESC) RN FROM MyTable)
WHERE RN = 1
(this query will always return only one row per C value)
OR
WITH CTE_Group AS
(
SELECT C, MAX(A) AS MaxA
FROM MyTable
GROUP BY C
)
SELECT g.MaxA, t.B, g.C
FROM MyTable t
INNER JOIN CTE_Group g ON t.A = g.MaxA AND t.C = g.C
(if there are multiple rows that have same Max(A) value - this query will return all of them)
Try Following Query :
SELECT TABLE1.A , TABLE2.B , TABLE1.C
FROM
(
SELECT MAX(A) AS A,C
FROM MYTable
GROUP BY C
) AS TABLE1
INNER JOIN
(
SELECT *
FROM MYTable
) AS TABLE2 ON TABLE1.A = TABLE2.A
SQLFIDDLE
you can do it by simple join query . join query always run faster then In query . Join query run only one time at the time of execution of the query . we can archive same result by using IN query .
SELECT t1.*
FROM YourTable t1
Left Outer Join YourTable t2 on t1.C=t2.C AND t1.A < t2.A
WHERE t2.A is null
how about this:
SELECT *
FROM MyTable
WHERE A IN (SELECT MAX(A) FROM MyTable GROUP BY C)
SELECT Max(A)
FROM MyTable
Where B=(SELECT Max(A) FROM MyTable)
update:
SELECT *
FROM MyTable
Where B=(SELECT Max(A) FROM MyTable)
update 2:
SELECT DISTINCT A, B
FROM MyTable
Where A=(SELECT Max(A) FROM MyTable GROUP BY C)
update 3:
ok, I think I understand what you're looking for now.. How about this:
SELECT *
FROM MyTable
Where A in (SELECT Max(A) FROM MyTable GROUP BY C)
WITH
cte AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY cola desc) AS Rno,
*
FROM
tbl
)
SELECT top 1
cola,colb
FROM
cte
order by Rno
Then try it:
WITH
cte AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY col3 ORDER BY col1 desc) AS Rno,
*
FROM
tbl
)
SELECT
col1,col2,col3
FROM
cte
WHERE Rno=1
I have a table that has an integer column named ID with values that may have gaps (e.g. 1,2,3,4,7,8,10,14,15,16,20)
I would like to find a query that would, in the example above, result in this:
1-4
7-8
10
14-16
20
= UPDATE =
Thanks to the code below (which seems to work well in SQL Server), I feel I am very close to getting this to work in MS-Access which is the goal. I'm still getting a syntax error though in my statment which I can't figure out...
SELECT val FROM
(
SELECT islands.PORTID, CSTR(islands.PORTID ) as val
FROM MYTABLE islands
WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = islands.PORTID - 1)
AND NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = islands.PORTID + 1)
UNION
SELECT
rngStart.PORTID
,CSTR(rngStart.PORTID ) + '-'
+ CSTR(MIN(rngEnd.PORTID)) as val
FROM MYTABLE rngStart
INNER JOIN MYTABLE checkNext ON checkNext.PORTID = rngStart.PORTID + 1
INNER JOIN
(
SELECT PORTID
FROM MYTABLE tblRangeEnd
WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = tblRangeEnd.PORTID + 1)
) rngEnd on rngEnd.PORTID > rngStart.PORTID
WHERE NOT EXISTS (SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngStart.PORTID - 1)
GROUP BY rngStart.PORTID
) as tbl
ORDER BY PORTID ASC
SELECT val FROM
(
-- Get the islands
SELECT islands.ID, CAST(islands.ID as varchar(10)) as val
FROM #t1 islands
WHERE NOT EXISTS (SELECT * FROM #t1 t2 WHERE t2.ID = islands.ID - 1)
AND NOT EXISTS (SELECT * FROM #t1 t2 WHERE t2.ID = islands.ID + 1)
UNION
-- Get the ranges
SELECT
rngStart.ID
,CAST(rngStart.ID as varchar(10)) + '-'
+ CAST(MIN(rngEnd.ID) as varchar(10)) as val
FROM #t1 rngStart
INNER JOIN #t1 checkNext ON checkNext.ID = rngStart.ID + 1
INNER JOIN
(
SELECT ID
FROM #t1 tblRangeEnd
WHERE NOT EXISTS (SELECT * FROM #t1 t2 WHERE t2.ID = tblRangeEnd.ID + 1)
) rngEnd on rngEnd.ID > rngStart.ID
WHERE NOT EXISTS (SELECT * FROM #t1 t2 WHERE t2.ID = rngStart.ID - 1)
GROUP BY rngStart.ID
) as tbl
ORDER BY ID ASC
I used a table variable called #t1 but just replace that with your table name.
Here it is in action.
EDIT
To make this work in Access you will have to change the joins a little bit. Try this:
SELECT val FROM
(
SELECT islands.PORTID, CSTR(islands.PORTID) as val
FROM MYTABLE islands
WHERE NOT EXISTS
(SELECT * FROM MYTABLE t2 WHERE t2.PORTID = islands.PORTID - 1)
AND NOT EXISTS
(SELECT * FROM MYTABLE t2 WHERE t2.PORTID = islands.PORTID + 1)
UNION
SELECT
rngStart.PORTID
,CSTR(rngStart.PORTID) + '-' + CSTR(MIN(endPORTID)) as val
FROM MYTABLE rngStart
INNER JOIN
(
SELECT checkNext.PORTID as nextPORTID, rngEnd.PORTID as endPORTID
FROM MYTABLE checkNext
INNER JOIN
(
SELECT rngEnd.PORTID
FROM MYTABLE rngEnd
WHERE NOT EXISTS
(SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngEnd.PORTID + 1)
) AS rngEnd on rngEnd.PORTID > checkNext.PORTID - 1
) AS checkNext ON checkNext.nextPORTID = rngStart.PORTID + 1
WHERE NOT EXISTS
(SELECT * FROM MYTABLE t2 WHERE t2.PORTID = rngStart.PORTID - 1)
GROUP BY rngStart.PORTID
) as tbl
ORDER BY PORTID ASC
create table #sequence (id int not null primary KEY)
insert into #sequence(id)
select 1
union all select 2
union all select 3
union all select 4
union all select 7
union all select 8
union all select 10
union all select 14
union all select 15
union all select 16
union all select 20
--Find Contig ranges
select l.id as start,
(
select min(a.id) as id
from #sequence as a
left outer join #sequence as b on a.id = b.id - 1
where b.id is null
and a.id >= l.id
) AS fend
from #sequence as l
left outer join #sequence as r on r.id = l.id - 1
where r.id is null;
--Find missing values in sequence
select l.id + 1 as start, min(fr.id) - 1 as stop
from #sequence as l
left outer join #sequence as r on l.id = r.id - 1
left outer join #sequence as fr on l.id < fr.id
where r.id is null and fr.id is not null
group by l.id, r.id;
drop table #sequence
This will give you both the ranges and the gaps between the ranges so you can see what you have or what you need. sample data provided
This will work if you access to function row_number().
with C as
(
select ID,
ID - row_number() over(order by ID) as grp
from YourTable
)
select min(ID) as MinID,
max(ID) as MaxID
from C
group by grp
or with a sub-query instead of a common table expression.
select min(ID) as MinID,
max(ID) as MaxID
from (select ID,
ID - row_number() over(order by ID) as grp
from YourTable) as C
group by grp
Result:
MinID MaxID
----------- -----------
1 4
7 8
10 10
14 16
20 20
Try it on SQL Server https://data.stackexchange.com/stackoverflow/q/119411/
Another try:
SELECT
MIN(i), MAX(i)
FROM (
select
i - (SELECT COUNT(*) FROM tbl t WHERE t.i < tbl.i) g,
i
from tbl
) t
GROUP BY g
It'll be slow for sure, but I don't see other way to number rows in access.