连接提供重复的行,我如何过滤它们?

时间:2018-01-06 14:26:55

标签: sql sql-server join

在这里,我不会只为每个" TourId"获得一行,但它为每个" TourId"提供多​​行。我该怎么办呢?请告诉我可以改善这种观点的可行方法。

ALTER VIEW Bill AS

            SELECT  Tour.TourId,
                    Itinerary.ItineraryId,
                    Tour.StartDate,
                    Tour.EndDate,
                    DATEDIFF(day,Tour.StartDate,Tour.EndDate) AS Duration,
                    Itinerary.EstTravelDist,
                    Guide.IdNo,
                    CAST(5000 * DATEDIFF(day,Tour.StartDate,Tour.EndDate) AS money) AS PaymentfoGuide,
                    SpecialActivity.Cost AS SpecielActivityCost,
                    VisitingPlaces.Cost AS VisitingPlaceTicketCost,
                    Tour.NumberOfPeople,
                    CAST( UnitPrice * Tour.NumberOfPeople AS money) AS CostForMeal,
                    Accommodation.Location AS Accomadation,
                    CAST(UnitPrice * NumberOfPeople * DATEDIFF(day,StartDate,EndDate) AS money) AS TotalAccommodationCost,
                    CAST(Itinerary.EstTravelDist * 40 AS money) AS TourPackegeCost, 
                    SpecialActivity.Cost * Tour.NumberOfPeople AS TotalSpecielActivityCost,
                    VisitingPlaces.Cost * Tour.NumberOfPeople AS  TotalVisitingPlaceTicketCost,
                    CAST(Itinerary.EstTravelDist * 40 + SpecialActivity.Cost * Tour.NumberOfPeople + VisitingPlaces.Cost * Tour.NumberOfPeople + 
                    UnitPrice * DATEDIFF(day,Tour.StartDate,Tour.EndDate) 
                    + 5000 * Tour.NumberOfPeople * DATEDIFF(day,Tour.StartDate,Tour.EndDate) + 
                    UnitPrice * DATEDIFF(day,Tour.StartDate,Tour.EndDate) * Tour.NumberOfPeople AS money) AS FINAL_COST

            FROM (((((((((Itinerary
            INNER JOIN SpecialActivity ON
            Itinerary.ItineraryId = SpecialActivity.ItineraryId)
            INNER JOIN VisitingPlaces ON
            VisitingPlaces.ItineraryId = Itinerary.ItineraryId)
            RIGHT JOIN Tour ON
            Tour.TourId = Itinerary.TourId)
            LEFT JOIN Guide ON
            Guide.TourId = Tour.TourId)
            INNER JOIN Vehicle ON
            Vehicle.TourId = Tour.TourId)
            INNER JOIN Accommodation ON
            Accommodation.TourId = Tour.TourId)
            INNER JOIN Participant ON
            Participant.TourId = Tour.TourId)
            INNER JOIN Person ON
            Person.IdNo = Guide.IdNo)
            INNER JOIN Contract ON 
            Contract.ItineraryId = Itinerary.ItineraryId)

SELECT * FROM Bill

2 个答案:

答案 0 :(得分:0)

你需要自己解决一些问题。

首先尝试将SELECT更改为SELECT DISTINCT。然后,每个TourID只会获得一行,如果SELECT列表中的每个其他项目对于该ID都是唯一的,但如果一个TourID可以有多个(例如)SpecialActivity记录,那么您将需要考虑更多:

对于SELECT列表中每个TourID有多个结果的每个项目,您需要考虑要显示的内容:例如,您可能将每个特殊活动的所有不同成本汇总在一起。您可能只想要第一个值或最高值的其他项目等。在这些情况下使用聚合函数,并在结尾处将其余字段添加到GROUP BY子句中。一个粗略的例子可能看起来像

        SELECT  Tour.TourId,
                Itinerary.ItineraryId,
                Tour.StartDate,
                Tour.EndDate,
                DATEDIFF(day,Tour.StartDate,Tour.EndDate) AS Duration,
                Itinerary.EstTravelDist,
                MAX(Guide.IdNo),
                SUM(CAST(5000 * DATEDIFF(day,Tour.StartDate,Tour.EndDate)) AS money) AS PaymentfoGuide,
                SUM(SpecialActivity.Cost) AS SpecialActivityCost,
                SUM(VisitingPlaces.Cost) AS VisitingPlaceTicketCost,
                Tour.NumberOfPeople,
                SUM(CAST( UnitPrice * Tour.NumberOfPeople AS money) AS CostForMeal),
                MAX(Accommodation.Location) AS Accomodation,
                SUM(CAST(UnitPrice * NumberOfPeople * DATEDIFF(day,StartDate,EndDate) AS money)) AS TotalAccommodationCost,
                SUM(CAST(Itinerary.EstTravelDist * 40 AS money)) AS TourPackegeCost, 
                SUM(SpecialActivity.Cost * Tour.NumberOfPeople) AS TotalSpecialActivityCost,
                SUM(VisitingPlaces.Cost * Tour.NumberOfPeople) AS  TotalVisitingPlaceTicketCost,
                SUM(CAST(Itinerary.EstTravelDist * 40 + SpecialActivity.Cost * Tour.NumberOfPeople + VisitingPlaces.Cost * Tour.NumberOfPeople + 
                UnitPrice * DATEDIFF(day,Tour.StartDate,Tour.EndDate) 
                + 5000 * Tour.NumberOfPeople * DATEDIFF(day,Tour.StartDate,Tour.EndDate) + 
                UnitPrice * DATEDIFF(day,Tour.StartDate,Tour.EndDate) * Tour.NumberOfPeople AS money)) AS FINAL_COST

        FROM (((((((((Itinerary
        INNER JOIN SpecialActivity ON
        Itinerary.ItineraryId = SpecialActivity.ItineraryId)
        INNER JOIN VisitingPlaces ON
        VisitingPlaces.ItineraryId = Itinerary.ItineraryId)
        RIGHT JOIN Tour ON
        Tour.TourId = Itinerary.TourId)
        LEFT JOIN Guide ON
        Guide.TourId = Tour.TourId)
        INNER JOIN Vehicle ON
        Vehicle.TourId = Tour.TourId)
        INNER JOIN Accommodation ON
        Accommodation.TourId = Tour.TourId)
        INNER JOIN Participant ON
        Participant.TourId = Tour.TourId)
        INNER JOIN Person ON
        Person.IdNo = Guide.IdNo)
        INNER JOIN Contract ON 
        Contract.ItineraryId = Itinerary.ItineraryId)

GROUP BY            Tour.TourId,
                    Itinerary.ItineraryId,
                    Tour.StartDate,
                    Tour.EndDate,
                    DATEDIFF(day,Tour.StartDate,Tour.EndDate) AS Duration,
                    Itinerary.EstTravelDist,
                    Tour.NumberOfPeople

然而,这是对数据结构的巨大假设。可能有必要进一步将查询分解为逻辑块以处理联接中的一对多关系。例如,您可能希望对除SpecialActivity和VisitingPlaces之外的所有表进行分组和聚合,如果这些是唯一的问题1:N关系,则将这些表分别连接到分组和聚合查询的输出。

还可以考虑将参与者表格移除到简单的联接:它似乎没有必要。

答案 1 :(得分:0)

从我所看到的情况来看,如果没有查看查询或数据库结构的结果,我无法确切地确认这一点,那么您就有一对多的关系:例如,1 TourID可能有很多行程。

如果需要,可以将查询视为表单,然后使用DISTINCT关键字从中访问数据。或者,如果您知道导致一对多关系的原因,您可以在其上使用聚合(如COUNT),并使用附加到查询末尾的GROUP BY

供参考:Group ByDistinct