ceturtdiena, 2010. gada 4. novembris

Bitwise OR, jeb kā caur vienu parametru var padot vairākas vērtības?

Rakstā ar piemēru aprakstīts Bitwise OR iekš SQL Server. Droši vien noderētu priekšzināšanas par Būla algebru.

Bij tāds specifisks gadījums- sākotnēji biju izveidojis tabulu, kurā bija bit kolona- tātad ar divām vērtībām jā/nē. Bija arī lietotāja interfeiss kurā bija ar radio-pogu (vai tā to sauc Latviski?) iespējams izvēlēties vērtības- jā/nē/visas. Izveidots arī pārskats, kas izsauc procedūru, kurai parametrs @Par, kas tika izmantots vaicājuma where daļā (Where IrKautKas = @Par OR @Par is Null). Tādējādi varēju atlasīt visu vajadzīgo. Prasībām mainoties parādījās vajadzība pēc vēl divām vērtībām šajā pašā laukā (piemēram, IrKlients- Jā/Nē jāpārveido par Klients "Parasts klients"/"Ilgadējs"/"Bijušais"/"Nav klients". un jāvar izvēlēties jebkura kombinācija- piemēram, atlasīt visus tos uzņēmumus, kas ir bijušie vai arī nav bijuši mūsu klienti). Pēc pamatīgām pārdomām par vismazāk sāpīgo izvēlējos zemāk aprakstīto risinājumu.

Situācijas ilustrācijai neliela testa tabula ar dažām vērtībām (Kolonnā "Skaitlis" ievietotās vērtības nav nejaušas):
Create Table dbo.TestTable
(
    TestTableID int primary key identity(1,1),
    Skaitlis int,
    Teksts NVarChar(10)
)
Go
Insert Into TestTable (Skaitlis, Teksts) Values (1, 'ridniņa 1')
Insert Into TestTable (Skaitlis, Teksts) Values (2, 'ridniņa 2')
Insert Into TestTable (Skaitlis, Teksts) Values (4, 'ridniņa 3')
Insert Into TestTable (Skaitlis, Teksts) Values (8, 'ridniņa 4')
Un tagad vaicājums, ko izmantoju:
Declare @Sk int
Set @Sk = 7

Select * From dbo.TestTable Where Skaitlis | @Sk = @Sk
Un rezultātā mēs esam ieguvuši vaicājumu, kur ar viena parametra palīdzību iespējams nofiltrēt pilnīgi jebkuru vērtību kombināciju, ja "Skatlis" kolonnā ievadītās vērtība vienmēr ir no kopas {1, 2, 4, 8, 16, .. , 2^n}.

Tas ko es izmantoju ir bitwise OR, kas strādā tā (x un y domāti biti, savukārt trešajā kolonā rezultāts, ja tiem pa vidu ir šis OR):
X
Y
OR (|)
0
0
0
0
1
1
1
0
1
1
1
1

Izvēlētie skaitļi kolonnā "Skaitlis" ir šādi:
Skaitlis
Bināri
1
0001
2
0010
4
0100
8
1000

Un Where daļa strādā tā (Pirmā kolonna- @Sk parametra vērtība cipariskā formā, otrā kolonna- kā @Sk vērtība izskatās bināri. Pārējās kolonās- ar "X" iezīmēts, ja šīs kolonnas vērtība tiks atlasīta pie attiecīgās parametra vērtības):

@Sk
@Sk bināri
Skatilis = 1 0001
Skatilis = 2 0010
Skatilis = 4 0100
Skatilis = 8 1000
1
0001
X



2
0010

X


3
0011
X
X


4
0100


X

5
0101
X

X

6
0110

X
X

7
0111

X
X
X
8
1000



X
9
1001
X


X
10
1010
X
X


Un tā tālāk ..

Priekšrocības risinājumam:
  • pietiek ar vienu parametru lai atlasītu jebkuru vērtību kombināciju, kas atbilst vajadzībām
  • no iepriekšējā punkta izriet- nav vajadzīgs dinamisks vaicājums, var vienkāršā viedā izmantot procedūru.
  • atlase strādā ātri un saprotot risinājumu, tas arī sāk izskatīties ļoti vienkārši
  • programmas interfeisu viegli pielāgot- manā situācijā izveidoju check-box lauciņiņus, kuriem apakšā slēpjas vērtības (1,2,4,8, ...) un izsaucot procedūru vienkārši sasummēju ieķeksētās vērtības, rezultātā iegūstot filtru pēc ieķeksētajām vērtībām.
Trūkumi:
  • Int ir 4 baiti, tas nozīmē, ka katra rinda var saturēt sevī kādu no 32 unikālām vērtībām (1 baits = 8 biti, katra unikālā vērtība- tikai viens bits ir ar vērtību '1', pārējie ar vērtību '0'. Tā kā int sastāv no 4 baitiem = 32 bitiem, tātad 32 unikālas vērtības). Protams, var izvēlēties citu datu tipu.
Izveidotās tabulas dzēšanas skripts:
Drop Table dbo.TestTable

Nav komentāru:

Ierakstīt komentāru