I've used the same cte several times in one script without issues, but I just wanted to double-check.
Let's say my script looks like this:
;with cte as
(
select provider, count(*) as 'rows_count'
from table1
) select *From cte
;with cte as
(
select fname, count(*) as 'totals'
from table_another
) select *From cte
;with cte as
(
select sum(sales) as 'total_sales
from table_yet_another
) select *From cte
Are there any issues to using the same cte with different select statements? Or should they have different names?
The name only needs to be unique within a single statement. So what you have is okay (if a bit confusing), but this would not be:
with cte as
(
select provider, count(*) as 'rows_count'
from table1
), cte as
(
select fname, count(*) as 'totals'
from table_another
) select *From cte
That is not the same query. A cte may only have one select statement. So that is three distinct statements.
The scope of a CTE is local to the statement. You can repeat them between different statements (but not twice in the same one). Although I would recommend using meaningful names for each one, just like you would with a table.
Related
Since I am not that familiar with Outer Apply, I am a bit lost with rewriting the one from my previous question to join. It worked well but not for large chunks of data. Any help with this appreciated.
Previous question
You might use the following approach:
Use a CTE to create a set and use ROW_NUMBER to number your calls.
ROW_NUMBER allows to specify the OVER() clause with a PARTITION BY and an ORDER BY part
This will return a list of your phone calls, where each phone number as a consecutive index in the order of EntryTime.
You can then use a self-join to find the corresponding previous row.
declare #table table (
PhoneNumber nvarchar(20),
EntryTime datetime
)
insert into #table values ('(321) 546-7842', dateadd(hour,-30,getdate()));
insert into #table values ('(321) 546-7842', dateadd(hour,-3,getdate()));
insert into #table values ('(251) 546-9442', dateadd(hour,-2,getdate()));
WITH cte AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY PhoneNumber ORDER BY EntryTime) AS CallIndex
,t.*
FROM #table t
)
SELECT *
FROM cte t1
LEFT JOIN cte t2 ON t1.PhoneNumber=t2.PhoneNumber AND t1.CallIndex=t2.CallIndex-1
ORDER BY t1.PhoneNumber, t1.EntryTime;
I have the following table:
CREATE TABLE sometable (my_id INTEGER PRIMARY KEY AUTOINCREMENT, name STRING, number STRING);
Running this query:
SELECT * FROM sometable;
Produces the following output:
1|someone|111
2|someone|222
3|monster|333
Along with these three fields I would also like to include a count representing the amount of times the same name exists in the table.
I've obviously tried:
SELECT my_id, name, count(name) FROM sometable GROUP BY name;
though that will not give me an individual result row for every record.
Ideally I would have the following output:
1|someone|111|2
2|someone|222|2
3|monster|333|1
Where the 4th column represents the amount of time this number exists.
Thanks for any help.
You can do this with a correlated subquery in the select clause:
Select st.*,
(SELECT count(*) from sometable st2 where st.name = st2.name) as NameCount
from sometable st;
You can also write this as a join to an aggregated subquery:
select st.*, stn.NameCount
from sometable st join
(select name, count(*) as NameCount
from sometable
group by name
) stn
on st.name = stn.name;
EDIT:
As for performance, the best way to find out is to try both and time them. The correlated subquery will work best when there is an index on sometable(name). Although aggregation is reputed to be slow in MySQL, sometimes this type of query gets surprisingly good results. The best answer is to test.
Select *, (SELECT count(my_id) from sometable) as total from sometable
The inner query in the following SQL statement is to normalize part of the database (code1, code2, code3, etc.) With the outer query I want to select the codes that aren't in the lookup table (tblicd)
select primarycode from
(
select id, primarycode from myTable
union
select id, secondarycode from myTable
union
select id, tertiarycode from myTable) as t
order by id
where primarycode not in tblicd.icd_id
The query above doesn't run, I'm wondering what I'm doing wrong. The error I get is the multi-part identifier tblicd.icd_id could not be bound
One problem is your ORDER BY and WHERE clauses are reversed. The ORDER BY clause must come after the WHERE clause.
Your WHERE clause is also incorrect. It should be like this:
WHERE primarycode NOT IN (SELECT icd_id FROM tblicd)
ORDER BY id
where primarycode not in tblicd.icd_id
might be
where primarycode not in (SELECT icd_id FROM tblicd )
I'm trying to SUM two rows obtained from differente SQL queries in UNION, is this possible?
All I can achieve is the two separate rows but I can't SUM them, DB engine keeps me telling that there's an error in the syntax near the *) FROM (the part next to the SUM)...
Here's the query:
SELECT * FROM
(SELECT COUNT(*) as cntclients
FROM
(SELECT DISTINCT clientkey AS clients
FROM <table>
WHERE <conditions...>)
) AS clients
) cntclients
UNION
(SELECT SUM(occurrences) AS cntclientsad
FROM <table2>
WHERE <conditions...>
)
This throws me for example:
cntclients
----------
901
50
Adding a SELECT SUM(*) FROM instead of the SELECT * FROM in the first line, and surrounding the two queries with parentheses just throws me the mentioned error...
I would like
cntclients <- or whatever name...
----------
951
Any ideas how this sum should work?
You don't actually need to use a UNION for this - you can just add them together manually:
SELECT a.countKey + b.sumOccur as total
FROM (SELECT COUNT(DISINCT clientkey) as countKey
FROM <table>
WHERE <conditions>) as a
CROSS JOIN (SELECT SUM(occurrences) as sumOccur
FROM <table2>
WHERE <conditions>) as b
select SUM(cntcol)
from
(
select count(*) as cntcol from sometables
union all
select SUM(occurrances) as cntcol from somemoretables
) ctquery
If you want to stick with the UNION you can write it this way:
SELECT sum(c.cntclients) as Totalcntclients
FROM
(
SELECT COUNT(*) as cntclients
FROM
(SELECT DISTINCT clientkey AS clients
FROM <table>
WHERE <conditions...>
) AS clients
UNION
SELECT SUM(occurrences) AS cntclientsad
FROM <table2>
WHERE <conditions...>
) c
You could also use:
SELECT
( SELECT COUNT(DISTINCT clientkey) as countKey
FROM <table>
WHERE <conditions>
)
+
( SELECT SUM(occurrences) as sumOccur
FROM <table2>
WHERE <conditions>
)
AS total
The approach that I took for this was to create a View for the UNION query. Then you can simply use
SELECT SUM(cntclients) FROM <view>
I got a database named accounts and account table inside of this database, Also I got the database named players and player table inside of this database.
How can I get a rows count of this two tables in one query?
I've tried this:
SELECT
SUM(`account`.`account`.`id`) AS 'accounts',
SUM(`player`.`player`) AS 'players';
But it doesn't work.
If you need exactly rows count (not sum), than do something like this:
select
(select count(*) from accounts.account) as count1,
(select count(*) from players.player) as count2
or
select count(*) as `count`,"account" as `table` from accounts.account
union all
select count(*) as `count`,"player" as `table` from players.player
A simple UNION operation on two select statements will do:
SELECT COUNT(*), 'Accounts' FROM Accounts.Account
UNION
SELECT COUNT(*), 'Players' FROM Players.Player
And you have to qualify each table with the database name since they're in separate databases.
Try:
SELECT
COUNT(`account`.`id`) AS 'accounts',
COUNT(`player`.`player`) AS 'players'
FROM
`account`,
`player`
SELECT COUNT(*)
FROM (
SELECT Id
FROM accounts.account
UNION ALL
SELECT player
FROM players.player ) AS BothTables
with Value (nbr, name ) as
(
select count(*) amount, 'AccountsCount' as ab from accounts..account
union all
select count(*) amount, 'PlayersCount' as ab from players..player
)
select *
from value as s
PIVOT(sum(nbr) for name in (AccountsCount, PlayersCount) ) as pvt