webdork
asked on
SQL view returns same item multiple times
How can i prevent the attached statement from returning the same item multiple times?
SELECT dbo.PLFDProducts.ProductID, dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.ExpirationDate,
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts INNER JOIN
dbo.PLFDProductDiscounts ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.ProductID INNER JOIN
dbo.PLFDDiscounts ON dbo.PLFDProductDiscounts.DiscountID = dbo.PLFDDiscounts.discountid
WHERE (dbo.PLFDDiscounts.Active <> N'no') AND (dbo.PLFDDiscounts.ExpirationDate > { fn NOW() }) AND (dbo.PLFDProducts.Active <> N'no')
DISTINCT would be the obvious choice, though it is quite slow.
SELECT DISTINCT dbo.PLFDProducts.ProductID, dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.ExpirationDate,
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts INNER JOIN
dbo.PLFDProductDiscounts ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.ProductID INNER JOIN
dbo.PLFDDiscounts ON dbo.PLFDProductDiscounts.DiscountID = dbo.PLFDDiscounts.discountid
WHERE (dbo.PLFDDiscounts.Active <> N'no') AND (dbo.PLFDDiscounts.ExpirationDate > { fn NOW() }) AND (dbo.PLFDProducts.Active <> N'no')
ASKER
both of those statements return the same set as without the DISTINCT
I don't know what results your looking for but why not a outer join on some of the tables? From either what I put here in this window or the window below.
SELECT
dbo.PLFDProducts.ProductID ,
dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.Expirati onDate,
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts
INNER JOIN dbo.PLFDProductDiscounts
ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.P roductID
right outer JOIN dbo.PLFDDiscounts
ON dbo.PLFDProductDiscounts.D iscountID = dbo.PLFDDiscounts.discount id
WHERE (dbo.PLFDDiscounts.Active <> N'no')
AND (dbo.PLFDDiscounts.Expirat ionDate > { fn NOW() })
AND (dbo.PLFDProducts.Active <> N'no')
SELECT
dbo.PLFDProducts.ProductID
dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.Expirati
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts
INNER JOIN dbo.PLFDProductDiscounts
ON dbo.PLFDProducts.ProductID
right outer JOIN dbo.PLFDDiscounts
ON dbo.PLFDProductDiscounts.D
WHERE (dbo.PLFDDiscounts.Active <> N'no')
AND (dbo.PLFDDiscounts.Expirat
AND (dbo.PLFDProducts.Active <> N'no')
SELECT
dbo.PLFDProducts.ProductID,
dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.ExpirationDate,
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts
INNER JOIN dbo.PLFDProductDiscounts
ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.ProductID
Left outer JOIN dbo.PLFDDiscounts
ON dbo.PLFDProductDiscounts.DiscountID = dbo.PLFDDiscounts.discountid
WHERE (dbo.PLFDDiscounts.Active <> N'no')
AND (dbo.PLFDDiscounts.ExpirationDate > { fn NOW() })
AND (dbo.PLFDProducts.Active <> N'no')
Frequently issues like this come from join conditions returning multiple records for fields that you do not intend. Are some of these tables one to many relationships? Maybe you have multiple entries for the same product in your Discounts table in which case if you have multiple active records you are going to return multiple records.
The query you are looking for, in that case, might involve using an aggregate (Possibly MAX) and a group by clause. Can you post the specifics of the tables involved?
The query you are looking for, in that case, might involve using an aggregate (Possibly MAX) and a group by clause. Can you post the specifics of the tables involved?
ASKER
how do i determine if one to many?
what table specifics do you want to see?
what table specifics do you want to see?
Paste your table structures in here.
Table structure (Column list) would be good to see. A one to many relationship would mean that there are multiple instances of the same product ID in the discount table, or any other table. To determine one to many just check the related tables to see if you find multiple instances of a product_id table. Any table that has a product_id field without a primary key (OR unique index) on the product_id field would be a one to many.
ASKER
Like this?
USE [**********]
GO
/****** Object: Table [dbo].[PLFDProducts] Script Date: 11/12/2008 09:36:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[PLFDProducts](
[Active] [nvarchar](4) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Break1] [int] NULL,
[Break2] [int] NULL,
[Break3] [int] NULL,
[CategoryID] [int] NULL,
[Description] [nvarchar](3000) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[DietStats] [nvarchar](2000) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Image] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Price] [smallmoney] NULL,
[Price2] [smallmoney] NULL,
[Price3] [smallmoney] NULL,
[Product] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[ProductWeight] [int] NULL,
[TimeKey] [smalldatetime] NULL,
[UnitsPerCase] [int] NULL,
[ServingSuggestions] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[ShelfLife] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL
) ON [PRIMARY]
USE [**********]
GO
/****** Object: Table [dbo].[PLFDProducts] Script Date: 11/12/2008 09:36:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[PLFDProducts](
[Active] [nvarchar](4) COLLATE SQL_Latin1_General_CP1_CI_
[Break1] [int] NULL,
[Break2] [int] NULL,
[Break3] [int] NULL,
[CategoryID] [int] NULL,
[Description] [nvarchar](3000) COLLATE SQL_Latin1_General_CP1_CI_
[DietStats] [nvarchar](2000) COLLATE SQL_Latin1_General_CP1_CI_
[Image] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_
[Price] [smallmoney] NULL,
[Price2] [smallmoney] NULL,
[Price3] [smallmoney] NULL,
[Product] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[ProductWeight] [int] NULL,
[TimeKey] [smalldatetime] NULL,
[UnitsPerCase] [int] NULL,
[ServingSuggestions] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_
[ShelfLife] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_
) ON [PRIMARY]
Yes, that works. Just add the other tables in your query as well.
ASKER
USE [****************]
GO
/****** Object: Table [dbo].[PLFDDiscounts] Script Date: 11/12/2008 09:38:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[PLFDDiscounts](
[discountid] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Description] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Type] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Amount] [int] NULL,
[DiscountCode] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Ceiling] [smallmoney] NULL,
[Active] [nvarchar](3) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[ExpirationDate] [datetime] NULL,
[ProductSpecific] [nvarchar](3) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL,
[Secret] [nvarchar](3) COLLATE SQL_Latin1_General_CP1_CI_ AS NULL CONSTRAINT [DF_PLFDDiscounts_Secret] DEFAULT (N'no')
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[PLFDDiscounts] Script Date: 11/12/2008 09:38:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[PLFDDiscounts](
[discountid] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_
[Description] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_
[Type] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_
[Amount] [int] NULL,
[DiscountCode] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_
[Ceiling] [smallmoney] NULL,
[Active] [nvarchar](3) COLLATE SQL_Latin1_General_CP1_CI_
[ExpirationDate] [datetime] NULL,
[ProductSpecific] [nvarchar](3) COLLATE SQL_Latin1_General_CP1_CI_
[Secret] [nvarchar](3) COLLATE SQL_Latin1_General_CP1_CI_
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
yeah and the other table
ASKER
USE [***********]
GO
/****** Object: Table [dbo].[PLFDProductDiscount s] Script Date: 11/12/2008 09:39:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[PLFDProductDiscount s](
[id] [int] IDENTITY(1,1) NOT NULL,
[ProductID] [int] NULL,
[DiscountID] [int] NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[PLFDProductDiscount
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[PLFDProductDiscount
[id] [int] IDENTITY(1,1) NOT NULL,
[ProductID] [int] NULL,
[DiscountID] [int] NULL
) ON [PRIMARY]
Run this query and tell me if you get different results in the discount id field. I suspect you have multiple discount IDs active causing you to get multiple records. You should see a unique combination of product IDs / discount IDs.
SELECT dbo.PLFDProducts.ProductID, dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.ExpirationDate, dbo.PLFDDiscounts.discountid
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts INNER JOIN
dbo.PLFDProductDiscounts ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.ProductID INNER JOIN
dbo.PLFDDiscounts ON dbo.PLFDProductDiscounts.DiscountID = dbo.PLFDDiscounts.discountid
WHERE (dbo.PLFDDiscounts.Active <> N'no') AND (dbo.PLFDDiscounts.ExpirationDate > { fn NOW() }) AND (dbo.PLFDProducts.Active <> N'no')
ASKER
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near '.'.
Incorrect syntax near '.'.
Sorry, missed a comma. Try this.
SELECT dbo.PLFDProducts.ProductID, dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.ExpirationDate, dbo.PLFDDiscounts.discountid,
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts INNER JOIN
dbo.PLFDProductDiscounts ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.ProductID INNER JOIN
dbo.PLFDDiscounts ON dbo.PLFDProductDiscounts.DiscountID = dbo.PLFDDiscounts.discountid
WHERE (dbo.PLFDDiscounts.Active <> N'no') AND (dbo.PLFDDiscounts.ExpirationDate > { fn NOW() }) AND (dbo.PLFDProducts.Active <> N'no')
SELECT
dbo.PLFDProducts.ProductID,
dbo.PLFDProducts.Product, dbo.PLFDDiscounts.Active, dbo.PLFDDiscounts.ExpirationDate,
dbo.PLFDProducts.Active AS Expr1
FROM dbo.PLFDProducts
LEFT OUTER JOIN dbo.PLFDProductDiscounts
ON dbo.PLFDProducts.ProductID = dbo.PLFDProductDiscounts.ProductID
RIGHT OUTER JOIN dbo.PLFDDiscounts
ON dbo.PLFDProductDiscounts.DiscountID = dbo.PLFDDiscounts.discountid
WHERE (dbo.PLFDDiscounts.Active <> N'no')
AND (dbo.PLFDDiscounts.ExpirationDate > { fn NOW() })
AND (dbo.PLFDProducts.Active <> N'no')
ASKER
same set with multiples
Can you post a small snippet of the result set? Just a couple of the rows that are the same?
ASKER
here it is
96 Peanut Butter Cookie yes 2008-11-17 00:00:00.000 72 Yes
94 Muffin Tops Assortment Box yes 2008-11-17 00:00:00.000 71 Yes
94 Muffin Tops Assortment Box yes 2008-11-30 00:00:00.000 64 Yes
97 Assorted Cookies yes 2008-11-17 00:00:00.000 71 Yes
97 Assorted Cookies yes 2008-11-30 00:00:00.000 64 Yes
85 Muffin Assortment Box yes 2008-11-30 00:00:00.000 64 Yes
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
They are not the same, have different dates. Use Mathew's suggestion and decide which one you want then set a min or max date
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
i've got to break off for a while. Work beckons.
Is it allowable to have multiple discounts active for the same product? If so your query is returning the correct results. If not, well, your query is still returning the right results and you just need to deactivate some of the discounts.
Enjoy work, I will be checking in later.
Enjoy work, I will be checking in later.
Open in new window