Is there any way to combine 2 SQL queries into a single query?
The table names used in both the SQL queries are same. The condition in the WHERE clause changes in both the queries.
Query 1:
SELECT ID
,SUM(time_duration) AS total_timespent
,COUNT(pno) AS ts_cnt
FROM (SELECT LEAD(create_ts) OVER (PARTITION BY ID ORDER BY CAST(pno AS INT)) AS R1,
DATEDIFF('second',create_ts::timestamp ,LEAD::timestamp) AS time_dur
FROM table_name
)A
WHERE item_no = '5672'
AND page_url_v11 IS NOT NULL
GROUP BY ID
Query 2:
SELECT ID
,SUM(time_duration) AS search_timespent
,COUNT(pno) AS search_cnt
from (SELECT LEAD(create_ts) OVER (PARTITION BY ID ORDER BY CAST(pno AS INT)) AS R1,
DATEDIFF('second',create_ts::timestamp ,LEAD::timestamp) AS time_dur
FROM table_name
)A
WHERE item_no = '5646'
GROUP BY ID
Yes, it is possible to combine both of them using conditional aggregation:
WITH A AS (
SELECT *
,LEAD(create_ts) OVER (PARTITION BY ID ORDER BY CAST(pno AS INT)) AS R1
,DATEDIFF('second',create_ts::timestamp ,LEAD::timestamp) AS time_duration
FROM table_name
)
SELECT
ID
,SUM(CASE WHEN item_no = '5672' AND page_url_v11 IS NOT NULL
THEN time_duration END) AS total_timespent
,COUNT_IF(item_no = '5672' AND page_url_v11 IS NOT NULL) AS ts_cnt
,SUM(CASE WHEN item_no = '5646' THEN time_duration END) AS search_timespent
,COUNT_IF(item_no = '5646') AS search_cnt
FROM A
GROUP BY ID;
You could use Union operation to join statements together.
If you want duplicates use UNION ALL ,
If you don't want duplicates use UNION
Related
I have a database where I have MenuItem, Item, Item_Details, and Item_Category tables. I would like to get an Item which is most frequently used in Menu.
SELECT
ItemName,
Category,
ItemPrice
FROM
restuarant.Menu_Item,
restuarant.Item,
restuarant.Item_Details,
restuarant.Item_Type
WHERE ItemId = Id_Item
AND ItemTypeId = Id_ItemType
AND ItemDetailsId = Id_ItemDetails
AND ItemId =
(SELECT ItemId
FROM restuarant.Menu_Item
HAVING COUNT(ItemId) =
(SELECT MAX(COUNT(ItemId))
FROM restuarant.Menu_Item
GROUP BY Id_MenuItem);
So the problems is I'm performing my subqueries incorrectly, I'm getting an error 'Cannot perform an aggregate function on an expression containing an aggregate or a subquery.'
How about the following:
SELECT TOP (1) ItemId, COUNT(ItemId) AS MCOUNT
FROM Menu_Item
GROUP BY ItemId
ORDER BY COUNT(ItemId) DESC
Example 1:
select aic.County, count(*) from Address_Information_County aic
group by aic.County
having count(*) = (select top 1 count(*) from Address_Information_County group by County order by count(*) desc);
Example 2:
select aic.County, count(*) from Address_Information_County aic
group by aic.County
having count(*) = (select max(cnt) from (select count(*) cnt from Address_Information_County group by County) x);
You could use "Group By" aggregate function to achieve this.
SELECT ItemID, count(*) as cnt
FROM restaurant r
GROUP BY r.ItemID
ORDER BY cnt desc
LIMIT 1;
In case, there are multiple entries that have count same as MaxCount, the following query would work.
SELECT ItemID, count(*) as cnt
FROM restaurant r
GROUP BY r.ItemID
HAVING count(*) =
(
SELECT count(*) as max_cnt
FROM restaurant r2
GROUP BY r2.ItemID
ORDER BY max_cnt desc
LIMIT 1
)
;
Currently I'm writing two queries to count distinct occurrences of fieldOne for each possible value of fieldTwo. How can I do this in one query? Thanks
select
count(*) from(select distinct(fieldOne) from myTable where fieldTwo= 'valueOne')x
select
count(*) from(select distinct(fieldOne) from myTable where fieldTwo = 'valueTwo') y
Try using CASE statement
SELECT COUNT(DISTINCT CASE WHEN FIELDTWO= 'VALUEONE' THEN FIELDONE END) X ,
COUNT(DISTINCT CASE WHEN FIELDTWO= 'VALUETWO' THEN FIELDONE END)Y
FROM MYTABLE
This can be done with cross apply to remove the need to know the possible values in fieldTwo:
select twos.FieldTwo, count(1)
from (select distinct fieldTwo from MyTable) twos
cross apply (select distinct t.fieldOne
from MyTable t
where t.fieldTwo = twos.FieldTwo) ones
group by twos.FieldTwo
I am trying to group by a column. The problem is that the NULL values of the column are grouped as a separate group.
I want the NULL values to be added to each of the other group values instead.
Example of a table:
The results I want to get from group by with sum aggregation over the 'val' column:
Can anyone help me?
Thanks!
You can precalculate the value to spread through the rows and then just do arithmetic:
select t.id,
sum(t.val) + (null_sum / cnt_id)
from t cross join
(select count(distinct id) as cnt_id,
sum(case when id is null then val else 0 end) as null_sum
from t
) tt
group by t.id;
Note some databases do integer division, so you might need null_sum * 1.0 / cnt_id.
A GROUP BY operation can't really generate values for each group on the fly, so logically you need records which are missing to really be present.
One approach is to use a calendar table to generate a table containing one NULL record for each id group:
WITH ids AS (
SELECT DISTINCT id FROM yourTable
WHERE id IS NOT NULL
),
cte AS (
SELECT t1.id, t2.val
FROM ids t1
CROSS JOIN yourTable t2
WHERE t2.id IS NULL
)
SELECT t.id, SUM(t.val) AS val
FROM
(
SELECT id, val FROM yourTable WHERE id IS NOT NULL
UNION ALL
SELECT id, val FROM cte
) t
GROUP BY
id;
Demo
does anyone know how can I subtract top two rows from one column only using one id? Here's my sample query:
SELECT top 2 a.consumption,
coalesce(a.consumption -
(SELECT b.consumption
FROM tbl_t_billing b
WHERE b.id = a.id + 1), a.consumption) AS diff
FROM tbl_t_billing a
WHERE a.customerId = '5'
ORDER BY a.dateCreated DESC
I want to know how to get the difference between the top 2 rows using one id from the consumption column using the customerId #5. I've tried but I can't get the right query for that. Can somebody help me please? Thanks!
try this:
;with cte as
(
select consumption, customerId,
row_number() over (partiton by customerid order by datecreated desc) rn
from tbl_t_billing where customerId = '5'
)
select a.customerId, a.consumption,
coalesce((a.consumption - b.consumption), a.consumption) consumption_diff
from cte a left outer join cte b on a.rn + 1 = b.rn
where a.rn = 1
declare #tbl_t_billing table(consumption int, customerId int, datecreated datetime)
insert into #tbl_t_billing
values
(10,5,'20100101'),
(7,5,'20000101'),
(9,4,'20100101'),
(5,4,'20000101'),
(8,3,'20100101'),
(3,3,'20000101'),
(7,2,'20100101'),
(3,2,'20000101'),
(4,1,'20100101'),
(2,1,'20000101')
-- get the difference between the last two consumption values for each customerId
select
customerId,
sum(consumption) diff
from(
select
customerId,
consumption *
case row_number() over(partition by customerId order by datecreated desc)
when 1 then 1 when 2 then -1
end consumption
from #tbl_t_billing
) t
group by customerId
I have two columns:
namecode name
050125 chris
050125 tof
050125 tof
050130 chris
050131 tof
I want to group by namecode, and return only the name with the most number of occurrences. In this instance, the result would be
050125 tof
050130 chris
050131 tof
This is with SQL Server 2000
I usually use ROW_NUMBER() to achieve this. Not sure how it performs against various data sets, but we haven't had any performance issues as a result of using ROW_NUMBER.
The PARTITION BY clause specifies which value to "group" the row numbers by, and the ORDER BY clause specifies how the records within each "group" should be sorted. So partition the data set by NameCode, and get all records with a Row Number of 1 (that is, the first record in each partition, ordered by the ORDER BY clause).
SELECT
i.NameCode,
i.Name
FROM
(
SELECT
RowNumber = ROW_NUMBER() OVER (PARTITION BY t.NameCode ORDER BY t.Name),
t.NameCode,
t.Name
FROM
MyTable t
) i
WHERE
i.RowNumber = 1;
select distinct namecode
, (
select top 1 name from
(
select namecode, name, count(*)
from myTable i
where i.namecode = o.namecode
group by namecode, name
order by count(*) desc
) x
) as name
from myTable o
SELECT max_table.namecode, count_table2.name
FROM
(SELECT namecode, MAX(count_name) AS max_count
FROM
(SELECT namecode, name, COUNT(name) AS count_name
FROM mytable
GROUP BY namecode, name) AS count_table1
GROUP BY namecode) AS max_table
INNER JOIN
(SELECT namecode, COUNT(name) AS count_name, name
FROM mytable
GROUP BY namecode, name) count_table2
ON max_table.namecode = count_table2.namecode AND
count_table2.count_name = max_table.max_count
I did not try but this should work,
select top 1 t2.* from (
select namecode, count(*) count from temp
group by namecode) t1 join temp t2 on t1.namecode = t2.namecode
order by t1.count desc
Here are to examples that you could use but the temp table use is more efficient than the view, but was done on a small data sample. You would want to check your own statistics.
--Creating A View
GO
CREATE VIEW StateStoreSales AS
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank'
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
GO
SELECT * FROM StateStoreSales
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP VIEW StateStoreSales
---Using a Temp Table
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank' INTO #TEMP
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
SELECT * FROM #TEMP
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP TABLE #TEMP