I have created a view using the following code
CREATE VIEW dbo.two_weeks_performance WITH SCHEMABINDING
AS
SELECT dbo.day_dim.date_time AS Date,
dbo.order_dim.quantity AS Target_Acheived
FROM dbo.day_dim
JOIN dbo.order_fact ON dbo.day_dim.day_id = dbo.order_fact.day_id
JOIN dbo.branch_dim ON dbo.order_fact.branch_id = dbo.branch_dim.branch_id
JOIN dbo.order_dim ON dbo.order_fact.order_id = dbo.order_dim.order_id
GROUP BY dbo.order_dim.quantity, dbo.day_dim.date_time`
Now when I use:
CREATE UNIQUE CLUSTERED INDEX two_weeks_performance_I ON two_weeks_performance (Date)
I am getting an error:
Cannot create index because its select list does not use the correct usage of COUNT_BIG(). Consider adding COUNT_BIG(*) to the select.
Please help me solve this issue.
The error tells you exactly what you have to do - add COUNT_BIG(*) to your select list.
From Creating Indexed Views:
If GROUP BY is specified, the view
select list must contain a
COUNT_BIG(*) expression, and the view
definition cannot specify HAVING,
ROLLUP, CUBE, or GROUPING SETS.
CREATE VIEW dbo.two_weeks_performance WITH SCHEMABINDING
AS
SELECT dbo.day_dim.date_time AS Date,
dbo.order_dim.quantity AS Target_Acheived,
COUNT_BIG(*) as Cnt
FROM dbo.day_dim
JOIN dbo.order_fact ON dbo.day_dim.day_id = dbo.order_fact.day_id
JOIN dbo.branch_dim ON dbo.order_fact.branch_id = dbo.branch_dim.branch_id
JOIN dbo.order_dim ON dbo.order_fact.order_id = dbo.order_dim.order_id
GROUP BY dbo.order_dim.quantity, dbo.day_dim.date_time
GO
CREATE UNIQUE CLUSTERED INDEX two_weeks_performance_I ON two_weeks_performance (Date)
Related
I'm trying to compose a UNION query between 2 tables and paginate the results. The problem is the INNER JOINS results in duplicate parent rows in the results so the pagination is incorrect.
I've created a dummy db to illustrate what I'm trying to do.
[Here's the schema diagram]
This is the SQL I have so far:
SELECT * FROM
(
SELECT 'Delivery' as [table_name]
,[Delivery].Id
,[Delivery].StreetAddress
,[Delivery].City
,[Delivery].[State]
,[Delivery].Zip
,[Delivery].Longitude
,[Delivery].Latitude
,[Delivery].OrderId
,[Order].[Date] AS 'Date'
,[Order].Total AS 'Total'
,[OrderProduct].[Name]
FROM [Delivery]
INNER JOIN [Order] ON [Delivery].OrderId = [Order].Id
INNER JOIN [OrderProduct] ON [Order].Id = [OrderProduct].OrderId
UNION
SELECT 'Collection' as [table_name]
,[Collection].Id
,[Collection].StreetAddress
,[Collection].City
,[Collection].[State]
,[Collection].Zip
,[Collection].Longitude
,[Collection].Latitude
,[Collection].OrderId
,[Order].[Date] AS 'Date'
,[Order].Total AS 'Total'
,[OrderProduct].[Name]
FROM [Collection]
INNER JOIN [Order] ON [Collection].OrderId = [Order].Id
INNER JOIN [OrderProduct] ON [Order].Id = [OrderProduct].OrderId
) AS Result
ORDER BY Result.Id
OFFSET 0 ROWS
FETCH NEXT 1000 ROWS ONLY
GO
There are multiple OrderProducts per Order so the results contain duplicate Result.Id. I've tried to use GROUP BY on the Result.Id but I get this error 'Column 'Result.table_name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.' How do I achieve correct pagination in this scenario?
Furthermore I need to consume the results in EntityFramework Core 2.2. Unfortunately I can't upgrade to a later version.
Many thanks
My schema:
I need to get count of comment for each tag.
I created a view:
create view dbo.UserTagCommentCount
with schemabinding
as
select
c.UserPK, t.PK TagPK, count_big(*) Count
from
dbo.Comments c
join
dbo.Posts p on p.PK = c.PostPK
join
dbo.PostTags pt on pt.PostPK = p.PK
join
dbo.Tags t on t.PK = pt.TagPK
group by
t.PK, c.UserPK
go
and I created clustered unique index on this view:
create unique clustered index PK_UserTagCommentCount
on dbo.UserTagCommentCount(UserPK, TagPK)
go
But when I select a rows by UserPK - this clustered index is not being used:
select *
from UserTagCommentCount
where UserPK = 19146
order by Count desc
OK. I create a simple index
create index IX_UserTagCommentCount_UserPK
on UserTagCommentCount(UserPK)
go
and use select with it
select *
from UserTagCommentCount with(index(IX_UserTagCommentCount_UserPK))
where UserPK = 19146
order by Count desc
but I see the same plan
Please any ideas? Why are the indexes not used when selecting from this view?
SQL Server 2019 development
I'm trying to run the SUM of MAX values, and then updating them into a column. I think the derived table is the right way to go, but now I keep getting a multi-part id could not be bound error that I dont know how to get round.
I'm running this on SSMS, and it will be my Db for a PowerApp. I'm essentially trying to take the distinct or MAX values of Assessment Hours from multiple Units, then add those together, grouped by the Staff ID number. I'm working with a derived table to try and mix the two aggregate functions.
WITH pretotalAssessment as
(
SELECT dbo.StaffTotals.Entry_ID, ISNULL(SUM(maxAssess),0) AS maxAssessHours
FROM
(
SELECT dbo.StaffTotals.Entry_ID, dbo.Units.[Unit Name],
ISNULL(MAX(dbo.Units.[Assessment Hours]),0) AS maxAssess
FROM dbo.Units
INNER JOIN dbo.StaffTotals ON dbo.StaffTotals.Entry_ID = dbo.Units.Entry_ID
GROUP BY dbo.StaffTotals.Entry_ID,dbo.Units.[Unit Name]
)Units
)
UPDATE preStaffTotals
SET preStaffTotals.Assessment = pretotalAssessment.maxAssessHours
FROM dbo.StaffTotals AS preStaffTotals
INNER JOIN pretotalAssessment ON preStaffTotals.Entry_ID = pretotalAssessment.Entry_ID;
My error is:
"The multi-part identifier "dbo.StaffTotals.Entry_ID" could not be bound."
I'm still quite new to SQL, so this is all a learning curve for me!
Your first SELECT in the CTE is from a derived table. That means that dbo.StaffTotals isn't accessible in the SELECT list.
You need to replace:
SELECT dbo.StaffTotals.Entry_ID
With:
SELECT Units.Entry_ID
You are SELECTING the full [schema].[tableName].[columnName] of dbo.StaffTotals.Entry_ID FROM Units.
Change to the below and it should work;
WITH pretotalAssessment as
(
SELECT Entry_ID, ISNULL(SUM(maxAssess),0) AS maxAssessHours
FROM
(
SELECT dbo.StaffTotals.Entry_ID, dbo.Units.[Unit Name],
ISNULL(MAX(dbo.Units.[Assessment Hours]),0) AS maxAssess
FROM dbo.Units
INNER JOIN dbo.StaffTotals ON dbo.StaffTotals.Entry_ID = dbo.Units.Entry_ID
GROUP BY dbo.StaffTotals.Entry_ID,dbo.Units.[Unit Name]
)Units
GROUP BY Entry_ID
)
UPDATE preStaffTotals
SET preStaffTotals.Assessment = pretotalAssessment.maxAssessHours
FROM dbo.StaffTotals AS preStaffTotals
INNER JOIN pretotalAssessment ON preStaffTotals.Entry_ID = pretotalAssessment.Entry_ID;
I would also suggest using COALESCE() instead of ISNULL() as COALESCE() is the ANSI standard and ISNULL() isn't. Also COALESCE() can have multiple arguments, whereas ISNULL() can only have 1. So easier for future dev changes. so;
WITH pretotalAssessment as
(
SELECT Entry_ID, COALESCE(SUM(maxAssess),0) AS maxAssessHours
FROM
(
SELECT dbo.StaffTotals.Entry_ID, dbo.Units.[Unit Name],
COALESCE(MAX(dbo.Units.[Assessment Hours]),0) AS maxAssess
FROM dbo.Units
INNER JOIN dbo.StaffTotals ON dbo.StaffTotals.Entry_ID = dbo.Units.Entry_ID
GROUP BY dbo.StaffTotals.Entry_ID,dbo.Units.[Unit Name]
)Units
GROUP BY Entry_ID
)
UPDATE preStaffTotals
SET preStaffTotals.Assessment = pretotalAssessment.maxAssessHours
FROM dbo.StaffTotals AS preStaffTotals
INNER JOIN pretotalAssessment ON preStaffTotals.Entry_ID = pretotalAssessment.Entry_ID;
SELECT
`bqm`.`project`.`project_id` AS `project_id`,
`bqm`.`project`.`project_name` AS `project_name`,
`bqm`.`project`.`project_manager` AS `project_manager`,
`bqm`.`project`.`updated_by` AS `updated_by`,
`bqm`.`project`.`created_dt` AS `created_dt`,
`bqm`.`project`.`updated_dt` AS `updated_dt`,
`bqm`.`project`.`archive` AS `archive_status`,
( SELECT
`u`.`user_name` AS NAME
FROM
(`bqm`.`project` `p`
right JOIN `bqm`.`user` `u` ON (`p`.`created_by`=`u`.`user_id`))) as Name
FROM
`bqm`.`project`;
I'm not sure what DBMS you're using as the syntax doean't appear to validate, but i'd move the join outside the select clause like so;
SELECT
Prj.project_id AS project_id,
Prj.project_name AS project_name,
Prj.project_manager AS project_manager,
Prj.updated_by AS updated_by,
Prj.created_dt AS created_dt,
Prj.updated_dt AS updated_dt,
Prj.archive AS archive_status,
Usr.User_name as Name
FROM bqm.project as Prj
Join bqm.user as Usr on Usr.user_id = Prj.created_By;
The issue you're getting is because the sub-query in the select clause isn't linked to the "main" query, meaning for every row in the Project table you'll have every row in the sub-query. By moving the join to the main query as I've suggested above will eliminate this.
My query:
IF OBJECT_ID ('vw_F_GWLVL_RAW', 'V') IS NOT NULL
DROP VIEW vw_F_GWLVL_RAW ;
GO
CREATE VIEW vw_F_GWLVL_RAW WITH SCHEMABINDING
AS
SELECT S.SiteName, CAST(D.[Date] as Date) as [Date], CONVERT(CHAR(5),T.[Time]) as [Time], CAST(F.SampleValue as NUMERIC(6,3)) as ValueAsRecorded,
Q.Code as DataQualityCode, Q.QualityDesc as DataQualityDesc
FROM dbo.F_GWLVL_RAW AS F INNER JOIN
dbo.D_Site AS S ON F.D_Site_Key = S.D_Site_Key INNER JOIN
dbo.D_Date AS D ON F.D_Date_Key = D.D_Date_Key INNER JOIN
dbo.D_Time AS T ON F.D_Time_Key = T.D_Time_Key INNER JOIN
dbo.F_ODP_QC_GWLVL AS Q ON Q.[Site] collate database_default = S.[SiteName] AND
(CONVERT(datetime,CAST(D.[Date] as VARCHAR(30))+' '+CAST(T.[Time] as VARCHAR(30)),121) BETWEEN Q.StartTime AND Q.EndTime)
GO
CREATE UNIQUE CLUSTERED INDEX IX_GWLVL_RAW1 ON vw_F_GWLVL_RAW(SiteName,[Date],[Time])
Gives me this error even though my convert is using deterministic 121 type:
'Cannot create index on view "dbo.vw_F_GWLVL_RAW". The view contains a convert that is imprecise or non-deterministic.'
Create INDEXED VIEWS.
You need to use a Deterministic Style in your CONVERT clause. The default is non-deterministic
Try,CONVERT(DECIMAL(10,2)) OR CONVERT(DATETIME, '20131202', 103)