0

I am developing a clinic management application.
In that application there is a part where doctors choose what they use up in each service they provide.
For example, when a doctor examines a patient, a pair of gloves and wooden stick are used and disposed of.

I use a trick that is simply, I create a string in the service table, that string has the IDs separated with comma (something like that 1,3,7,) and it works fine except for one case.
That case is when I want to display the used up item names as one column for multiple services.
I get items of service one plus service two and so on as one string for all service.
Is there any way I can solve that? I know it sounds complicated but If it works it will many other you read this.

The way I use to join is:

on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0  

Simply I cast the Used Item ID TblSupply.IDSupply as string then check if it exists in the service table.

When I display as separate columns, it works fine but I get multiple rows for the same service as follows:

Select
  TblService.ServiceName,
  TblSupply.SupplyName
from
  TblService
  left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0   

e.g.

 _____________________________________________
|TblService.ServiceName|TblSupply.SupplyName |
|Patient examination   |Glove                |
|Patient examination   |wood stick           |
|Patient examination   |thermometer          |
|Sonar   examination   |Glove                |
|Sonar   examination   |lubricating Gel      |
|Consultation          |Glove                |
|______________________|_____________________|

I want to get

________________________________________________________
|TblService.ServiceName|xxxxx                           |
|Patient examination   |Glove ,wood stick , thermometer |
|Sonar   examination   |Glove,lubricating Gel           |
|Consultation          |Glove                           |

The code I made

Select
   TblService.ServiceName,TempTable.SupplyList
from
   TblService
   left join (Select TblService.IDService As IDService,
                     STUFF((Select ', ' + TblSupply.SupplyName
                            FROM
                              TblService
                              left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
                              FOR XML PATH('')), 1, 1, '') as SupplyList
              FROM
                  TblService
              GROUP BY
                  TblService.IDService
             ) as TempTable on TempTable.IDService=TblService.IDService  

I tried

Select
    TblPatientService.IDPatientService,
    TblService.ServiceName,
    TempTable.SupplyList
from
    TblPatientService
    left Join TblService On TblService.IDService = TblPatientService.IDService 
    left join (Select TblPatientService.IDPatientService As IDPatientService
                      STUFF((Select ', ' + TblSupply.SupplyName
                             FROM
                                TblPatientService
                                left join TblService on TblService.IDService = TblPatientService.IDService
                                left join TblSupply on CHARINDEX(CAST(TblSupply.IDSupply as varchar(10)), TblService.UsedSupplyIDs) > 0
                             WHERE
                                TblPatientService.IDService = TblService.IDService
                             FOR XML PATH('')), 1, 1, '') as SupplyList
               FROM
                   TblPatientService
                   left Join TblService On TblService.IDService = TblPatientService.IDService
               GROUP BY
                   TblPatientService.IDPatientService
              ) as TempTable on TempTable.IDPatientService = TblPatientService.IDPatientService  

What I really get

|TblService.ServiceName|xxxxx                                                                         
|Patient examination   |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel   |
|Sonar   examination   |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel   |
|Consultation          |Glove ,wood stick , thermometer,Glove,lubricating Gel,Glove,lubricating Gel   |

In other words I get all the used items for all services as if they used for one service for all displayed.

GMB
  • 216,147
  • 25
  • 84
  • 135
hanyarnaoot
  • 13
  • 1
  • 4
  • Does this answer your question? [How to concatenate text from multiple rows into a single text string in SQL server?](https://stackoverflow.com/questions/194852/how-to-concatenate-text-from-multiple-rows-into-a-single-text-string-in-sql-serv) – XAMT Jan 11 '20 at 08:26
  • What version of Sql Server? Just asking because starting from version 2017 one could use [STRING_AGG](https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql). – LukStorms Jan 11 '20 at 09:01
  • 1
    "that string has the IDs separated with comma (something like that 1,3,7,)". WRONG. That is not the SQL way to store data. Use a junction/association table. – Gordon Linoff Jan 11 '20 at 12:07

2 Answers2

2

Since SQL Server 2017, you can use STRING_AGG. Somtehing like :

SELECT TblPatientService.IDPatientService AS IDPatientService, 
       STRING_AGG(TblSupply.SupplyName, ', ') AS SupplyList
FROM   TblPatientService
       LEFT OUTER JOIN TblService ON TblService.IDService = TblPatientService.IDService
       LEFT OUTER JOIN TblSupply ON CHARINDEX(CAST(TblSupply.IDSupply AS VARCHAR(10)), TblService.UsedSupplyIDs) > 0
GROUP BY TblPatientService.IDPatientService;

To replace XML stuff !

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
SQLpro
  • 3,994
  • 1
  • 6
  • 14
2

This is too long for a comment.

I would strongly suggest fixing your data model. Storing delimited lists in database columns is a typical design antipattern, that will backfire in different ways (complexity, efficiency, maintenance, data integrity). You can ha have a look at this famous SO question for more details.

As an exemple: your current join condition will not do what you expect for some supply ids that are more than one digit long (typically, 1 would match 10).

You should normalize your model and have a separate table to store the N-M relationship between services and supplies, with one tuple per row.

GMB
  • 216,147
  • 25
  • 84
  • 135
  • first , thank you for your time,GMB , Second I have solved the nearly all the problems except for this one, regarding id (typically, 1 would match 10). it format the number to be 000 so that 001 would not match 010 my expected range is about 5 or seven maximum 20 item, so I believe I am safe and if i need i can make 0000 – hanyarnaoot Jan 11 '20 at 12:17