【问题标题】:MySQL query to get all (additional) symptoms and diseases [closed]MySQL查询以获取所有(其他)症状和疾病[关闭]
【发布时间】:2015-06-13 22:46:07
【问题描述】:

我有一个包含主要症状、附加症状和疾病的数据库。我需要替换 2 个查询,因为我确信我的第一个查询效率不高,而我的第二个查询根本不正确。我希望任何人都可以帮助我,因为我是这个领域的新手..

数据库说明:

该数据库正在被医疗应用程序使用:

  1. 用户选择特定的身体部位
  2. 该应用列出了该特定身体部位的所有主要症状
  3. 用户选择主要症状(常见或不常见)
  4. 该应用列出了所选主要症状的所有疾病。还会出现 2 个可供用户选中的复选框(附加症状)。列出的疾病 (d_weight) 的顺序取决于年龄、性别、选定的主要症状以及用户选中的框。 d_weight d_weight > 5 的疾病被认为不太常见。用户输入的可能性(年龄、性别、身体部位、主要症状)存储在症状_疾病_组合表中。

    • asa_id 是所有适用症状的 ID(由用户检查的其他症状)
    • asc_id 是属于特定主要症状的附加症状的所有可能性的标识。例如,asc_id = 0,以防未选择其他症状。 asc_id = 1,以防仅选择附加症状“失眠”。 asc_id = 2,以防同时选择“失眠”和“爆炸”。

1.查询以获取特定身体部位的所有症状(可以改进):

SELECT DISTINCT s.name
              , s.id
              , sdc.s_common 
           FROM symptom as s
              , symptom_disease_combi as sdc 
          WHERE sdc.age = ".$age." 
            AND sdc.gender = ".$gender." 
            AND sdc.bodypart = ".$bodypart." 
            AND sdc.s_id = s.id

2。查询获取所选症状的所有疾病和附加症状(不起作用):

SELECT DISTINCT d.name
              , d.id
              , sdc.d_weight
              , adls.id
              , adls.name 
           FROM disease as d 
              , symptom_disease_combi as sdc
              , symptom as s
              , adlsymptom as adls 
          WHERE sdc.age = ".$age." 
            AND sdc.gender = ".$gender." 
            AND sdc.bodypart = ".$bodypart." 
            AND s.id = ".$sid." 
            AND sdc.s_id = s.id

3.数据库结构(如果我的设计可以改进,请告诉我)

CREATE TABLE symptom
(id INT NOT NULL AUTO INCREMENT
,name VARCHAR(100) DEFAULT NULL
,critical INT NOT NULL
,PRIMARY KEY (id)
) ENGINE=MyISAM;

id name                    critical
 1 Behavioral disturbances        1
 2 Ear pressure                   0
 3 Elevated temperature           0
 4 Fainting                       0
 5 Head pain                      0

CREATE TABLE disease (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(100) DEFAULT NULL,
critical int(11) NOT NULL,
description text NOT NULL,
tests text NOT NULL,
treatment text NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=19 DEFAULT CHARSET=latin1

id name                critical    description    tests       treatment
 1 Adjustment disorder 0           lorem ipsum    lorem ipsum lorem ipsum
 2 ADHD                0           lorem ipsum    lorem ipsum lorem ipsum
 3 Drug reaction       0           lorem ipsum    lorem ipsum lorem ipsum
 4 Seizure (epilepsy)  1           lorem ipsum    lorem ipsum lorem ipsum        

CREATE TABLE adlsymptom (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1

id name
 1 Insomnia
 2 Blowing up
 3 Depressed
 4 Drug abuse

CREATE TABLE adlsymptom_apply (
id int(11) NOT NULL,
as_id int(11) NOT NULL,
PRIMARY KEY (id,as_id),
KEY FK_additional_symptom_that_apply (as_id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

id as_id
 1 1
 1 2

CREATE TABLE adlsymptom_combi (
id int(11) NOT NULL,
as_id int(11) NOT NULL,
PRIMARY KEY (id,as_id),
KEY FK_additional_symptom_combination (as_id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

id as_id
 1 1
 2 2
 3 1
 3 2

CREATE TABLE symptom_disease_combi (
id int(11) NOT NULL AUTO_INCREMENT,
age int(11) NOT NULL,
gender int(11) NOT NULL,
bodypart int(11) NOT NULL,
s_id int(11) NOT NULL,
s_common int(11) NOT NULL,
asc_id int(11) NOT NULL,
asa_id int(11) NOT NULL,
d_id int(11) NOT NULL,
d_weight int(11) NOT NULL,
PRIMARY KEY (id),
KEY FK_symptom (s_id),
KEY FK_additional_symptom_combination (asc_id),
KEY FK_additional_symptom_that_apply (asa_id),
KEY FK_disease (d_id)
) ENGINE=MyISAM AUTO_INCREMENT=65 DEFAULT CHARSET=latin1

id age gender bodypart s_id s_common asc_id asa_id d_id d_weight
 1 1   1      1        1    1        0      1      1    1
 2 1   1      1        1    1        0      1      2    2  
 3 1   1      1        1    1        0      1      3    3
 4 1   1      1        1    1        0      1      11   4

更新 1:

  • 在疾病和症状中创建critical 是为了告诉用户,当他们点击疾病或症状时,他们需要立即去医院
  • agegenderbodypart 是 id,所以 age = 1,表示 0-5,age = 2 表示 6-17,age = 3 表示 18-59 和 age = 4 表示 60+。
  • 请看一下应用程序的设计,对理解数据库的设计有很大帮助:http://i.imgur.com/p9QP1av.pngBtw,在设计中;原因 == 疾病...
  • asa_id 指 adlsymptom_apply 的 id
  • asc_id 指 adlsymptom_combi 的 id
  • “distinct”仅用于获得所有症状/疾病 1 次。我确定它不需要,但我不知道如何解决它。

【问题讨论】:

  • 那么问题是什么?你在找什么?你有最终输出的样本吗?另外,请用您的表格和一些示例数据创建一个小提琴
  • 请学习使用明确的join 语法。一个简单的规则:永远不要在from 子句中使用逗号。
  • 把症状分成两张表有什么意义。这会让 2 张桌子连续流鼻涕?并维护第二个相交表,使连接复杂化并降低性能
  • @Engo,你能希望你的最终数据集是什么样子吗?另外,您能否将您的节目创建表作为文本而不是屏幕截图?
  • Engo 我认为你解释得很好。 Imo 问题在 2 小时后从桌面上掉下来,再加上你的问题需要大量的阅读和努力,这意味着在这样的论坛中几乎没有回应。很少有人愿意花时间帮助你

标签: mysql database database-design relational-database database-schema


【解决方案1】:

抛弃 2 个症状表,使用 1 个(症状)和 1 个相交表 (sdc)

我会在症状中添加新列,例如试图提升症状的状态/级别 不顾诱惑,对主要或次要的重要性,因为这很容易 让它不灵活。

例如,昏厥似乎主要是一种疾病/状况,但总体上可能会导致这种情况发生变化

求一般性,因此 1 个症状表,您正确地在 sdc 中有一个 d_weight

我喜欢你的 sdc.d_weight 概念。

例如,晕厥可能对癫痫有一定影响,但对流感则不然。整个概念 如果给患有流感的人开的是 Zarontin 而不是达菲,那就搞砸了

因为我喜欢你的 sdc.d_weight 概念,我想知道你为什么选择附加症状表

在表 sdc 中,您有名称以“FK_”开头的键/索引。希望你有实际的 FK 约束

而不仅仅是让你认为你拥有它们的命名约定(FK,你没有它们)

例如,身体部位、症状和疾病/状况的真实 FK。

当用户选择症状时,将它们从 GUI 中删除,以便再次添加该症状以进行搜索

这减少了工作并通过放弃辅助表(我所写和建议的第 1 行)来简化查询

再次注意,您使用 KEY(它是索引的同义词,而不是外键约束)只会创建 一个索引...

create table symptom
(
    id int not null auto_increment primary key,
    name varchar(100) not null, -- if you can't put a name to it, don't have it
    critical int not null
)ENGINE=MyISAM default charset=latin1;

create table disease
(
    id int not null auto_increment primary key, -- don't mix and match int with int(11)
    name varchar(100) not null, -- if you can't put a name to it, don't have it
    critical int not null,
    -- etc columns, text
)ENGINE=MyISAM default charset=latin1;

.

create table symptom_disease_combi
(   -- a.k.a. sdc
    id int not null auto_increment primary key, -- don't mix and match int with int(11)
    age int not null,
    gender char(1) not null,    -- int(11) is overkill
    bodypart int not null,
    s_id int not null,
    s_common int not null,
    asc_id int not null,
    asa_id int not null,
    d_id int not null,
    d_weight int not null,

    -- additional indexes (note pk above, so it is there and happy)

    -- note that some of your indexes (your KEYS) are worthless for the queries in question
    -- however they may be useful for other queries in your system
    -- for instance your asc and asa indexes will not be useful as they won't be picked up
    -- in relation to the question posed
    --
    -- you will need to find the proper balance of index bloat based on system needs

    INDEX idx_sdc_siddid (s_id,d_id,bodypart),  -- composite, general purpose
    INDEX idx_sdc_didsid (d_id,s_id,bodypart),  -- ditto but reverse
    INDEX idx_sdc_ascid (asc_id),
    INDEX idx_sdc_asaid (asa_id),
    -- put constraints here:
    CONSTRAINT `fk_sdc_bodypart` FOREIGN KEY (bodypart) REFERENCES bodypart(id),
    CONSTRAINT `fk_sdc_sid` FOREIGN KEY (s_id) REFERENCES symptom(id), -- don't mix and match int and int(11)
    CONSTRAINT `fk_sdc_did` FOREIGN KEY (d_id) REFERENCES disease(id)
    -- are there others, such as asc asa tables ??
)ENGINE=MyISAM default charset=latin1;

我认为您需要仔细考虑年龄列 sdc 是否会加载一个新行,每个年龄一个,50 到 120,性别='M',前列腺癌? 我是根据你的 age=xxxxx 行,也许你的意思是 >=。或白血病,

所以我从下面的查询中排除了年龄

——对于下一个查询,我想知道为什么你需要一个不同的? - 给定症状行是否有超过 1 个 sdc.s_common?只有你会知道 -- 如果不是,放弃独特的

-- join on 子句的顺序很重要,使其遵循良好的索引,以便快速返回结果

-- 我并不是说这些是被覆盖的索引,但是你会尽量减少表扫描活动

select distinct s.name, s.id, sdc.s_common
from symptom s
join symptom_disease_combi sdc
on sdc.s_id=s.id and sdc.bodypart=".$bodypart." and sdc.gender= ".$gender."

-- 不是我上面关于年龄的评论 -- 根据需要在计算列中合并权重

这些是我的建议,祝你好运

【讨论】:

  • 非常感谢您的回答,但我发现还有一些事情解释得不够清楚,所以我会更新我的帖子,提供一些关于您的问题的额外信息...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多