回答

收藏

SQL:如何遍历SELECT语句的结果?

技术问答 技术问答 308 人阅读 | 0 人回复 | 2023-09-13

如何在SQL中遍历SELECT语句的结果?我的SELECT语句将仅返回1列,但返回n个结果。
% d5 k4 i* F& V8 f7 p我在下面创建了一个虚构的场景,其中包含我想做的事情的伪代码。
0 B5 D( h% O* C' C+ r( r  ^设想:! L7 c; I0 |4 n9 Q
学生正在注册他们的课程。他们提交具有多个课程选择的表格(即一次选择3个不同的课程)。当他们提交注册时,我需要确保他们选择的课程还有剩余的空间(请注意,在向他们展示课程选择UI之前,我将进行类似的检查,但是之后我需要进行验证,以防其他人进入并刷卡剩下的位置)。
( {# q, Y  J8 p9 W3 q伪代码:( n( o; s( [/ k$ J0 q' ]0 J
DECLARE @StudentId = 1% s  v& x+ x1 R/ C- B4 O2 ^
DECLARE @Capacity = 20
2 ^8 p4 Y6 ^8 C1 q8 G* \-- Classes will be the result of a Select statement which returns a list of ints
& I/ o4 d# E: V) [$ p3 n1 R: R@Classes = SELECT classId FROM Student.CourseSelections
, a) r6 Q3 r& g/ ?, NWHERE Student.CourseSelections = @StudentId9 T+ R9 Q2 n. A
BEGIN TRANSACTION" s$ v5 L* E7 N- c0 ~! o4 {
DECLARE @ClassId int
2 G2 A: X1 s6 X. s, N- Uforeach (@classId in @Classes)
" a- H* w/ ]8 B0 u0 x) G{
& v- E$ d, l5 o3 p+ q) X   SET @SeatsTaken = fnSeatsTaken @classId
2 H. ~9 u2 o  Q' t% x7 i   if (@SeatsTaken > @Capacity)
6 a4 x$ q' W+ A( H+ K4 Z2 |   {, t) _' ~" F+ [& }5 H. [. j
       ROLLBACK;  -- I'll revert all their selections up to this point- e+ @2 J5 W; c; |. T2 N! @/ F/ Y
       RETURN -1;4 k( R* x5 r2 F: b
   }2 k- E2 F3 E. [4 }$ U
   else
2 d3 T, z' b5 ~  U   {/ Z+ S! E1 c+ X0 W( J# m+ P6 y
       -- set some flag so that this student is confirmed for the class
* j6 i5 \6 X) L* t, R   }
5 U  U1 U) R4 E! l}' ^8 v; N8 |$ M- u
COMMIT+ _% S8 q( \- i
RETURN 0
9 z7 G- a' b- G' W( I6 ]9 \我真正的问题是类似的“票务”问题。因此,如果此方法看起来非常错误,请随时推荐一些更实用的方法。
7 V; u/ m( f% N5 X) ^% g& D+ c编辑:
/ d% h7 r+ I. c/ }) X! ~1 s尝试实施以下解决方案。在这一点上,它是行不通的。始终返回“保留”。4 O2 ]% n+ c' o- }/ u6 t
DECLARE @Students TABLE
# O9 h; E7 N9 M  v; S& ~(
, \1 j! c" |% f. {8 N StudentId int+ m5 D0 _. p  P
,StudentName nvarchar(max). W: C# [/ Z6 x4 f. X3 J
)
; {. D/ B; T- d; Y: x' XINSERT INTO @Students4 ]  a' ]: N- n" H
(StudentId ,StudentName)
. V7 v8 g+ M6 ?5 |4 @VALUES; u5 r1 \) a, ^" f# w# M, s- {5 h  o
(1, 'John Smith')# d+ @& @8 V4 c+ C8 _
,(2, 'Jane Doe')" m; O" u7 p( T5 y* U
,(3, 'Jack Johnson')) _$ Q( E+ w. {9 X
,(4, 'Billy Preston')5 S. n6 S! N9 h9 j. a
-- Courses
- ]' R, Z& E1 c3 @. }) D+ ?/ |1 hDECLARE @Courses TABLE0 @+ n8 g% j) T+ Z: W( t. B
(
6 s( y! k- l5 X3 k$ c2 F( [ CourseId int
. q4 f" P; Z6 z. H,Capacity int
- S3 g( h1 ~: z! ~5 n; R( Q' ]8 Z$ N1 d9 _,CourseName nvarchar(max)
1 g! ]. R8 O3 `- B8 `0 q)
- _# u# L& n* a+ x# |$ T7 o( `INSERT INTO @Courses! k- r5 W7 A7 [! V! t4 m* _
(CourseId, Capacity, CourseName)9 s: h! y. H( W0 ^
VALUES! v0 K+ m7 H  q. T2 A' S# U
(1, 2, 'English Literature'),
% H8 J6 W, X5 ^. p8 m' N (2, 10, 'Physical Education'),
- G6 w) w$ a9 @: Z4 d (3, 2, 'Photography')1 x! Q) F* N1 d+ N

+ L( R3 x& F/ O6 n-- Linking Table( u: r& m2 }- i5 W4 i# O3 u2 E* K$ ?
DECLARE @Courses_Students TABLE9 r. `* ]* m! z
(' H" K8 d# R* d6 S, _, P
Course_Student_Id int
: w% H) a: M$ Z1 T,CourseId int/ F8 G: ?/ v4 {* E# o* g& Y
,StudentId int
, e# p2 F6 g# [1 o  z  x& s9 })- J, b5 @1 }% g& K8 x! q: C
INSERT INTO @Courses_Students
+ T6 r4 y% v8 p. P (Course_Student_Id, StudentId, CourseId)- x* _" T; I& A& c) f
VALUES
! ?, ~: `2 s' c0 u (1, 1, 1),
) I) D0 g, t* r: z( N! ? (2, 1, 3),/ _1 x% G  Z/ d' }
(3, 2, 1),7 @1 R# N% d/ N! O# t
(4, 2, 2),$ U# \; S2 w- y" e8 a& O# F* ^# R
(5, 3, 2),
# p; I. N) g1 [4 \, }7 t* ~ (6, 4, 1),
( `# t5 h- n2 u  X$ G0 U3 L% ` (7, 4, 2)8 b1 m7 L6 M0 Q4 k
SELECT Students.StudentName, Courses.CourseName FROM @Students Students INNER JOIN3 s# q4 w5 a3 G) Q( A0 [
@Courses_Students Courses_Students ON Courses_Students.StudentId = Students.StudentId INNER JOIN- `) w; v4 b( r* ^% H5 O1 B/ `" v* x
@Courses Courses ON Courses.CourseId = Courses_Students.CourseId
0 p- D- q8 g* o( H4 Z" b5 FDECLARE @StudentId int = 4
4 k2 x2 {/ W+ q8 N6 o) K-- Ideally the Capacity would be database driven
9 `% c5 M- G* @. ^8 g-- ie. come from the Courses.Capcity.2 D2 ]/ i7 e, l* W0 [% [
-- But I didn't want to complicate the HAVING statement since it doesn't seem to work already.
2 l9 G( E0 h. y9 o$ b% I2 aDECLARE @Capacity int = 1
5 {* P( u# `) UIF EXISTS (Select *
! ]) K* R. g+ s' p FROM9 S9 \" ^  t/ l) T3 P4 l; ~
  @Courses Courses INNER JOIN' W# w7 E  P" F# U, i
  @Courses_Students Courses_Students ON Courses_Students.CourseId = Courses.CourseId* s& y! m3 U* b% I0 A
WHERE
" \8 Z& e. ~3 L# z  Courses_Students.StudentId = @StudentId
1 I/ `! v5 {9 j, v1 K3 u9 K GROUP BY
/ l+ o/ ~% @: c' z7 n9 }3 q) [+ Y1 U; a  Courses.CourseId
! u. j* r# P% C1 ^' g5 b HAVING
: s: i2 O3 E9 J4 k  COUNT(*) > @Capacity)
2 K9 J% M% P5 \, l+ YBEGIN
6 d3 x& w' ?. Q1 H0 c SELECT 'full' as Status
5 g; P! U8 D  O7 e" M/ W1 i  BEND
7 m  N& ?. j7 l8 s6 uELSE BEGIN$ F  j6 ?9 w$ o6 \$ x- |/ [
SELECT 'reserved' as Status
) Y4 f- N$ j1 f: S0 Z& iEND
! A2 V- q" ]8 b/ l4 `! ]$ \: e4 N                  N/ j7 M9 c# A" A3 y
解决方案:
$ _9 A$ i3 F8 g+ _& X( S               
. K- K# k' x0 W  t6 o" y- K( _0 n  ?9 H' J! W
$ X9 r* f6 r7 U  I
                无需循环。您正在查看具有COUNT和GROUP的标准聚合。
$ C) }- A" V) ]2 o当然,需要一些细节,但是原理是…+ |# ?% y! {+ d" ^$ d# E4 r# z9 g
DECLARE @StudentId = 1
6 r2 q5 w. r3 D1 c3 Q1 CDECLARE @Capacity = 207 H. [2 W" v0 p. B/ g
-- Classes will be the result of a Select statement which returns a list of ints
( E1 Z+ {0 R0 i) c0 p9 SIF EXISTS (SELECT *
3 D4 ^; m: V2 K: h% v2 _    FROM
+ s* B7 c: {8 h( _        Student.CourseSelections CS1 O# N& J+ l. N
        JOIN
6 N, H8 \0 j5 `. Y/ x* z1 p        ---this is where you find out course allocations somehow' d7 q7 G+ o- ]$ Q7 j
        ClassTable C ON CS.classId = C.classId # A/ k  Y: ~# g
    WHERE
! k- |; {3 r) k3 j; [9 E; I        Student.CourseSelections = @StudentId- D) x0 `4 y( H% P2 ~/ K$ ^
    GROUP BY  --change this, it depends on where you find out course allocations
% c( ~( r+ o& ^        ClassID6 ]9 @; r: V1 \) g# x
    HAVING% U0 w" a: J( k, I3 `, V
        COUNT(*) > @Capacity)
; o9 c) t: h+ j6 o* Q8 H" r0 n, e   'no'
+ e2 h- {" G$ ~/ s3 pELSE
% ~" ~6 z! S( t3 Y" o' X   'yes'7 I  _6 I% D7 l2 B- u, n4 b
编辑:
* H4 l, K, t2 U3 i- @我已经更改了链接表。链接表中通常不需要Course_Student_ID。- L1 f! }8 r6 A" W& |; I
现在加入
4 a: K4 w2 y" b  N7 k+ F+ K9 t得到那个学生的课程, C) \- {8 {, F: R
然后查看本课程中的所有学生并与能力进行比较( k0 g# K3 p3 H, E

; o: n. |4 Y/ e! w  `缩减以上版本:
1 B( P1 V2 ?7 i. L$ U* Q...
$ e/ |' ?2 S5 \" s-- Linking Table, e7 g! V, r) j( o! U3 H
DECLARE @Courses_Students TABLE (
7 ]" f7 S# ?4 x2 H1 c" r# d$ s7 l( C,CourseId int
* z: v. E3 o  N3 k5 `8 ~3 c,StudentId int)& }5 d8 G9 S; f; ^
INSERT INTO @Courses_Students- W  g. j  B  N) C7 k# u
(StudentId, CourseId)
% d& d2 A& {3 Q  ZVALUES (1, 1), (1, 3), (2, 1), (2, 2), (3, 2), (4, 1), (4, 2)
# W! n; B5 d0 B9 ?DECLARE @StudentId int = 4! A8 m+ n4 G& z% T2 Q
--straight list. H# F3 Q- r5 i/ G
SELECT8 M& j* f( W( }1 ^
     C.CourseName, C.Capacity, COUNT(*)/ T1 E8 o9 n: Y. y
FROM$ w2 c4 E9 Q: _+ n, R/ W' x
  @Courses_Students CSThis. Z4 @" P/ q, r) L6 Z  L5 I' [
  JOIN# u" o6 ~5 c( D0 g: M: u
  @Courses C ON CSThis.CourseId = C.CourseId! b' l5 p( g& a& T, F( {
  JOIN) E9 B* P; r; y; z" B3 V
  @Courses_Students CSOthers ON CSOthers.CourseId = C.CourseId, |# ^; I3 ?4 H4 O- p
WHERE2 O' Y+ [5 {9 T* u& P5 \- D) P
  CSThis.StudentId = @StudentId
" O! T4 M! }; p% f- j$ T GROUP BY
1 D  d# q2 N2 I  C.CourseName, C.Capacity
, q" m% @" g5 F' z0 \--oversubscribed list
- @, W" y9 ~  F6 y3 g  SELECT
) A' B" N0 {: t. {; L8 }     C.CourseName, C.Capacity, COUNT(*)
3 y  m& ?# y9 w6 B; r! q: o FROM
% q2 H/ [1 c+ O  @Courses_Students CSThis5 c7 }) }: z9 D) g6 U( a- v
  JOIN8 ^) b: O4 \! f. D5 a
  @Courses C ON CSThis.CourseId = C.CourseId
- d: M7 b  H' O  JOIN- W. O( G/ V- u( _9 v7 y
  @Courses_Students CSOthers ON CSOthers.CourseId = C.CourseId
% `! k8 X* k& G8 `% D, r WHERE
6 f; N/ r1 U1 i/ F6 ]  CSThis.StudentId = @StudentId
% ^' \9 `( R7 s( a" W) Y# P& K GROUP BY
' s5 j* r2 X& b  C.CourseName, C.Capacity
) n: w4 D% i; F' x" \5 q& E  HAVING
; W! }3 D% T7 x9 A      COUNT(*) > C.Capacity
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则