SQLite 按位查询返回意外结果

问题描述 投票:0回答:1

这是我的查询(EF Core 7 和生成的原始 SQL):

Me.Context.Patients.Where(Function(Patient) Patient.BloodType.ReceivesFrom.HasFlag(BloodType))
SELECT "p"."Id", "p"."BloodTypeId", "p"."CityId", "p"."Code", "p"."Email", "p"."FirstName", "p"."LastName", "p"."ZipCodeId", "b"."Type"
      FROM "Patients" AS "p"
      INNER JOIN "BloodTypes" AS "b" ON "p"."BloodTypeId" = "b"."Id"
      WHERE ("b"."ReceivesFrom" & 4) = 4

...结果如下:

-------------------------------------------------------------------------------------------------------------
| Id | BloodTypeId | CityId |  Code | Email                    | FirstName  | LastName   | ZipCodeId | Type |
-------------------------------------------------------------------------------------------------------------
|  1 |           4 |     46 | U6UJI | [email protected]   | Abbigail   | Cremin     |        12 |    4 |
|  2 |           5 |     88 | LV892 | [email protected]       | Donnell    | McKenzie   |        94 |    8 |
|  5 |           8 |     44 | 5F6TN | [email protected] | Nedra      | Stokes     |        66 |   64 |
|  7 |           5 |     16 | 6LQ61 | [email protected]       | Jairo      | Jakubowski |        69 |    8 |
| 10 |           5 |      8 | BI56C | [email protected]   | Modesto    | Reichert   |        33 |    8 |
| 11 |           5 |     94 | R8LP2 | [email protected]    | Raphaelle  | Murphy     |        47 |    8 |
| 16 |           5 |     66 | 8TC6V | [email protected]      | Daphney    | Bechtelar  |        94 |    8 |
| 17 |           4 |     45 | DM52B | [email protected]     | Durward    | Larson     |        67 |    4 |
-------------------------------------------------------------------------------------------------------------

问题是查询结果非常不准确。

这是

BloodTypes
数据:

----------------------------------------
| Id | ReceivesFrom | DonatesTo | Type |
----------------------------------------
|  1 |            0 |         0 |    0 |
|  2 |            3 |       255 |    1 |
|  3 |            3 |       255 |    2 |
|  4 |           15 |       204 |    4 |
|  5 |           15 |       204 |    8 |
|  6 |           51 |       240 |   16 |
|  7 |           51 |       240 |   32 |
|  8 |          255 |       192 |   64 |
|  9 |          255 |       192 |  128 |
----------------------------------------

支持枚举:

<Flags>
Public Enum BloodTypes As Byte
  <Description("?")> Unknown = 0
  <Description("O+")> OPositive = 1
  <Description("O-")> ONegative = 2
  <Description("A+")> APositive = 4
  <Description("A-")> ANegative = 8
  <Description("B+")> BPositive = 16
  <Description("B-")> BNegative = 32
  <Description("AB+")> ABPositive = 64
  <Description("AB-")> ABNegative = 128
End Enum

...以及

Patients
数据(假的,用 Bogus 创建):

-----------------------------------------------------------------------------------------------------------
| Id | BloodTypeId| CityId | Code  | Email                           | FirstName | LastName   | ZipCodeId |
-----------------------------------------------------------------------------------------------------------
|  1 |          4 |     46 | U6UJI | [email protected]          | Abbigail  | Cremin     |        12 |
|  2 |          5 |     88 | LV892 | [email protected]              | Donnell   | McKenzie   |        94 |
|  3 |          6 |     85 | SNTB4 | [email protected]     | Paige     | Watsica    |         4 |
|  4 |          2 |     24 | 4XMHO | [email protected]              | Gregg     | Wilkinson  |        26 |
|  5 |          8 |     44 | 5F6TN | [email protected]        | Nedra     | Stokes     |        66 |
|  6 |          2 |     88 | 6C1LG | [email protected]             | Brice     | Runolfsson |        55 |
|  7 |          5 |     16 | 6LQ61 | [email protected]              | Jairo     | Jakubowski |        69 |
|  8 |          6 |     12 | 50U3K | [email protected]            | Fredy     | Heathcote  |        54 |
|  9 |          7 |      2 | DD4YB | [email protected]                | Dorothea  | Littel     |        20 |
| 10 |          5 |      8 | BI56C | [email protected]          | Modesto   | Reichert   |        33 |
| 11 |          5 |     94 | R8LP2 | [email protected]           | Raphaelle | Murphy     |        47 |
| 12 |          7 |     92 | AALG8 | [email protected]              | Willy     | Pouros     |        28 |
| 13 |          7 |     82 | LCH1T | [email protected]         | Everardo  | Lang       |         6 |
| 14 |          6 |      8 | 8HNN2 | [email protected] | Koby      | Purdy      |        53 |
| 15 |          3 |     24 | FWG31 | [email protected]      | Gardner   | Mueller    |        27 |
| 16 |          5 |     66 | 8TC6V | [email protected]             | Daphney   | Bechtelar  |        94 |
| 17 |          4 |     45 | DM52B | [email protected]            | Durward   | Larson     |        67 |
| 18 |          7 |     57 | 4750K | [email protected]           | Joelle    | Bashirian  |        58 |
| 19 |          2 |     18 | O8Z0Q | [email protected]           | Loy       | Ratke      |        98 |
| 20 |          1 |      6 | 8UKAB | [email protected]     | Christa   | Gibson     |        48 |
-----------------------------------------------------------------------------------------------------------

看到问题了吗?

A+
血液(
4
枚举中的
BloodTypes
标志)可以从类型
A+/-
O+/-
(来源:Red Cross)接收,因此查询应该返回恰好 11 行,其
BloodTypeId
2
3
4
5
。 (我已确保我的
Patients
测试数据中存在满足此要求的 11 个随机行。)

Flag

4
(
A+
) 的
ReceivesFrom
值为 15,它是
1
2
4
8
(
O+
O-
) 类型的总和A+
A-
)。

这是我的

BloodTypes
表定义(没有索引,但我怀疑这很重要):

CREATE TABLE "BloodTypes" (
    "Id"    INTEGER NOT NULL,
    "ReceivesFrom"  INTEGER NOT NULL DEFAULT 0,
    "DonatesTo" INTEGER NOT NULL DEFAULT 0,
    "Type"  INTEGER NOT NULL DEFAULT 0,
    CONSTRAINT "PK_BloodTypes" PRIMARY KEY("Id" AUTOINCREMENT)
);

令人沮丧的是查询结果包含无效行并省略有效行。例如,检查结果中的

ID#5
64
(
AB+
) 不可能适合
15
。这在数学上是不可能的。

PatientId
4
6
15
19
在哪里?为什么他们被省略了?他们在
A+
可接受的血型范围内。

这是怎么回事?为什么 SQLite 会产生如此不准确的结果?

sqlite entity-framework-core bitwise-operators bitwise-and
1个回答
0
投票

事实证明查询行为正确。我的期望是不正确的。我倒着看问题180°。

我们不应该试图将

AB+
(64) 塞进
A+.ReceivesFrom
聚合 (15) 中(这显然行不通),我们应该走另一条路,将
A+
(4) 放入
AB+.ReceivesFrom
聚合中( 255).

当我们分解它时,这是完全有道理的。

规则:我们希望所有可以从

A+
接受治疗的患者。简单。

根据

图表
,这是
A
AB。这两个的
ReceivesFrom
总数分别为 15 和 255。
A+
(4) 适合这两者,因此查询返回所有
A/AB
血型。

问题解决了。事实上,这从来都不是问题。

© www.soinside.com 2019 - 2024. All rights reserved.