SQL - 具有特定条件的重复行

时间:2018-04-30 04:57:06

标签: sql sql-server

我们有一个这样的表:

 +----+-------+-----------------+----------------+-----------------+----------------+-----------------+
| ID |  Name | RecievedService | FirstZoneTeeth | SecondZoneTeeth | ThirdZoneTeeth | FourthZoneTeeth |
+----+-------+-----------------+----------------+-----------------+----------------+-----------------+
|  1 |  John |   SomeService1  |       13       |                 |        4       |                 |
+----+-------+-----------------+----------------+-----------------+----------------+-----------------+
|  2 |  John |   SomeService1  |       34       |                 |                |                 |
+----+-------+-----------------+----------------+-----------------+----------------+-----------------+
|  3 | Steve |   SomeService3  |                |                 |                |        2        |
+----+-------+-----------------+----------------+-----------------+----------------+-----------------+
|  4 | Steve |   SomeService4  |                |                 |                |        12       |
+----+-------+-----------------+----------------+-----------------+----------------+-----------------+

区域中的每个数字都是牙齿(牙科学),这意味着“John”的牙齿#3有两次“SomeService1”。

+----+------+-----------------+----------------+-----------------+----------------+-----------------+
| ID | Name | RecievedService | FirstZoneTeeth | SecondZoneTeeth | ThirdZoneTeeth | FourthZoneTeeth |
+----+------+-----------------+----------------+-----------------+----------------+-----------------+
|  1 | John |   SomeService1  |       13       |                 |        4       |                 |
+----+------+-----------------+----------------+-----------------+----------------+-----------------+
|  2 | John |   SomeService1  |       34       |                 |                |                 |
+----+------+-----------------+----------------+-----------------+----------------+-----------------+

请注意,史蒂夫已经为牙齿#2(第四区)接受过两次服务,但服务不是一次。

我会编写一些代码,为我提供一个包含重复行的表(检查唯一的患者和接收的服务)(使用“group by”子句“),但我也需要检查区域。

我试过这个:

select ROW_NUMBER() over(order by vv.ID_sick) as RowNum,
        bb.Radif,
        bb.VCount as 'Count',
        vv.ID_sick 'ID_Sick', 
        vv.ID_service 'ID_Service',
        sick.FNamesick + ' ' + sick.LNamesick as 'Sick',
        serv.NameService as 'Service',
        vv.Mab_Service as 'MabService',
        vv.Mab_daryafti as 'MabDaryafti',
        vv.datevisit as 'DateVisit',
        vv.Zone1,
        vv.Zone2,
        vv.Zone3,
        vv.Zone4,
        vv.ID_dentist as 'ID_Dentist',
        dent.FNamedentist + ' ' + dent.LNamedentist as 'Dentist',
        vv.id_do as 'ID_Do',
        do.FNamedentist + ' ' + do.LNamedentist as 'Do'
     from visiting vv inner join (
            select ROW_NUMBER() OVER(ORDER BY a.ID_sick ASC) AS Radif,
            count(a.ID_sick) as VCount,
             a.ID_sick,
              a.ID_service 
             from visiting a 
        group by a.ID_sick, a.ID_service, a.Zone1, a.Zone2, a.Zone3, a.Zone4
        having count(a.ID_sick)>1)bb 
        on vv.ID_sick = bb.ID_sick and vv.ID_service = bb.ID_service 
        left join InfoSick sick on vv.ID_sick = sick.IDsick
        left join infoService serv on vv.ID_service = serv.IDService
        left join Infodentist dent on vv.ID_dentist = dent.IDdentist
        left join infodentist do on vv.id_do = do.IDdentist
        order by bb.ID_sick, bb.ID_service,vv.datevisit

但是这段代码只返回重复所有牙齿的行。我想要的是甚至一颗牙齿重复......

我该如何实施?

我需要检查区域中的字符。

** Zone的数据类型为varchar

1 个答案:

答案 0 :(得分:1)

对于您要执行的操作,这是一个糟糕的数据模型。通过将牙齿存储为varchar,您可以确定您对单颗牙齿不感兴趣,但仅限于牙齿组。然而,现在,你正试图研究单颗牙齿。

您需要这样的数据模型:

服务

+------------+--------+-----------------+
| service_id | Name   | RecievedService |
+------------+--------+-----------------+
|  1         |  John  |  SomeService1   |
+------------+--------+-----------------+
|  3         |  Steve |  SomeService3   |
+------------+--------+-----------------+
|  4         |  Steve |  SomeService4   |
+------------+-------+-----------------+

service_detail

+------------+------+-------+
| service_id | zone | tooth |
+------------+------+-------+
|  1         |  1   |  1    |
|  1         |  1   |  3    |
|  1         |  3   |  4    |
+------------+------+-------+
|  1         |  1   |  3    |
|  1         |  1   |  4    |
+------------+------+-------+
|  3         |  4   |  2    |
+------------+------+-------+
|  4         |  4   |  1    |
|  4         |  4   |  2    |
+------------+------+-------+

使用给定的数据模型可以使用递归查询和字符串操作即时创建此类表:

with unpivoted(service_id, name, zone, teeth) as
(
  select recievedservice, name, 1, firstzoneteeth
  from mytable where len(firstzoneteeth) > 0
  union all
  select recievedservice, name, 2, secondzoneteeth
  from mytable where len(secondzoneteeth) > 0
  union all
  select recievedservice, name, 3, thirdzoneteeth
  from mytable where len(thirdzoneteeth) > 0
  union all
  select recievedservice, name, 4, fourthzoneteeth
  from mytable where len(fourthzoneteeth) > 0
)
, service_details(service_id, name, zone, tooth, teeth) as
(
  select
    service_id, name, zone, substring(teeth, 1, 1), substring(teeth, 2, 10000)
  from unpivoted
  union all
  select
    service_id, name, zone, substring(teeth, 1, 1), substring(teeth, 2, 10000)
  from service_details
  where len(teeth) > 0
)
, duplicates(service_id, name) as
(
  select distinct service_id, name
  from service_details
  group by service_id, name, zone, tooth
  having count(*) > 1    
)
select m.*
from mytable m
join duplicates d on d.service_id = m.recievedservice and d.name = m.name;

由于数据模型错误,很多工作和相当慢的查询,但仍然可行。

Rextester演示:http://rextester.com/JVWK49901