Últimamente he estado ocupado y no tengo mucho tiempo para quedarme y escribir un blog. Por la noche, encontré un problema de SQL que encontré muy interesante, que puede ser útil para principiantes y novatos como yo, así que decidí compartirlo con todos.
Debido a que el autor es intrínsecamente torpe, no es riguroso en el pensamiento y realmente no es bueno para escribir declaraciones SQL, los maestros no se ríen, omita este artículo.
No introduciré mucho el fondo. Primero, cree una tabla e inserte los datos de prueba. Los campos tienen comentarios
--医生表
CREATE TABLE doctor
(
id INT IDENTITY(1, 1) , --ID 自增长
docNumber NVARCHAR(50) NOT NULL , --医生编码
NAME NVARCHAR(50) NOT NULL --医生姓名
)
go
--插入测试数据
INSERT INTO doctor
VALUES ( '007', 'Tom' )
INSERT INTO doctor
VALUES ( '008', 'John' )
INSERT INTO doctor
VALUES ( '009', 'Jim' )
--号源表(挂号表)
CREATE TABLE Nosource
(
id INT IDENTITY(1, 1) ,
docNumber NVARCHAR(50) NOT NULL , --和医生表中的医生编码对应
workTime DATETIME NOT NULL
)
go
--插入测试数据
INSERT INTO Nosource
VALUES ( '007', '20120819' )
INSERT INTO Nosource
VALUES ( '007', '20120820' )
INSERT INTO Nosource
VALUES ( '007', '20120821' )
INSERT INTO Nosource
VALUES ( '008', '20120821' )
Una vez construida la tabla, los datos de prueba también son correctos. Comencemos a hablar de la demanda.
1. Averigüe la información relevante de cada médico y la cantidad de fuentes que posee ese médico.
Esto es demasiado simple, tal vez incluso los amigos que acaban de aprender helloWorld y un poco de lo básico de la base de datos sean una tontería seria y sincera. Pero el código todavía está escrito.
--简单的分组查询即可搞定
SELECT COUNT(nos.id) AS PersonNumSounceCOUNT , --总数
dct.ID AS docID ,
dct.NAME ,
dct.docNumber ,
nos.workTime
FROM doctor AS dct
LEFT JOIN Nosource AS nos ON dct.docNumber = nos.docNumber
GROUP BY dct.ID ,
dct.NAME ,
dct.docNumber ,
nos.workTime
Es realmente sencillo. Se puede hacer un grupo pequeño. ¿Qué más vendes?
Ahora que la demanda cambia, debe coincidir de acuerdo con las condiciones: el tiempo de trabajo de la tabla de origen de números requeridos es mayor que la fecha actual para que sea válida, de lo contrario no coincidirá.
Si la condición workTime no coincide con la del médico, el valor del campo PersonNumSounceCOUNT correspondiente debe ser 0; por ejemplo, si el médico Jim no tiene una fuente de números calificada y coincidente, el valor del campo PersonNumSounceCOUNT debe ser 0. Mirando hacia el cielo 40 grados, piense en la capacidad de filtrar con la palabra clave where, y luego consultarlo todo a la vez. Intentalo.
SELECT COUNT(nos.id) AS PersonNumSounceCOUNT , --总数
dct.ID ,
dct.NAME ,
dct.docNumber ,
nos.workTime
FROM doctor AS dct
LEFT JOIN Nosource AS nos ON dct.docNumber = nos.docNumber
WHERE DATEDIFF(day, GETDATE(), nos.workTime) > 0
GROUP BY dct.ID ,
dct.NAME ,
dct.docNumber ,
nos.workTime
Creo que alguien escribirá el código anterior. Pero después de ejecutar la consulta, descubrí que no cumplía con los requisitos. Incluso la información básica y los registros de tablas del Dr. Jim se han filtrado y desaparecido. ¿Qué pasa?
La razón es simple. Utilice la palabra clave "where" después de la consulta de conexión para filtrar los datos en el conjunto de resultados de la consulta de conexión. Debido a que las condiciones de la tabla de la derecha (tabla de origen numérico) no coinciden, los datos de la tabla de la izquierda (tabla de doctor) también se filtrarán.
Por lo tanto, se producirá el fenómeno anterior (la información y los registros del Dr. Jim desaparecieron). ¿Es posible averiguarlo todo a la vez? ¿Cómo lograrlo?
De hecho, la escritura correcta debería ser así:
SELECT COUNT(nos.id) AS PersonNumSounceCOUNT , --总数
dct.ID ,
dct.NAME ,
dct.docNumber ,
nos.workTime
FROM doctor AS dct
LEFT JOIN ( SELECT *
FROM Nosource
WHERE DATEDIFF(day, GETDATE(), workTime) > 0
) AS nos ON dct.docNumber = nos.docNumber
GROUP BY dct.ID ,
dct.NAME ,
dct.docNumber ,
nos.workTime
Vuelva a realizarlo y resultará correcto, que es el resultado de cumplir con los requisitos. La idea es: solo es necesario filtrar la tabla correcta, usar el conjunto de resultados filtrado (usando una subconsulta) como la tabla derecha de la consulta de combinación, y luego conectar y agrupar ...
De hecho, escribir declaraciones SQL concisas y de alto rendimiento requiere fuertes habilidades de pensamiento lógico (inseparables de las matemáticas) y experiencia. Existe una forma más sencilla de escribir:
SELECT sum(case when nos.workTime>getdate then 1 else 0 end) AS PersonNumSounceCOUNT , --总数
dct.ID AS docID ,
dct.NAME ,
dct.docNumber
FROM doctor AS dct
LEFT JOIN Nosource AS nos ON dct.docNumber = nos.docNumber
GROUP BY dct.ID ,
dct.NAME ,
dct.docNumber
Para explicarlo de esta manera, no sé si todos pueden entenderlo. De todos modos, la idea general es así. La capacidad expresiva y el nivel del autor son ciertamente limitados, y es inevitable que haya desviaciones, ¡espero que los lectores lo comprendan!
Este artículo es de http://blog.csdn.net/dinglang_2009 , indique la fuente para la reimpresión.