任务(父)和任务实例(子):使用PHP和MySQL从6个图像中选择1个


Tasks (parent) and TaskInstances (child): choose 1 image out of 6 with PHP and MySQL?

我正在编译MySQL查询附带的HTML输出显示页面,但希望得到一些方向。任何帮助将非常感激!

背景:

TaskInstance是子进程,而Tasks和Students都是父进程。每次学生注册一个任务时,TaskInstance表都会不断增长,然而Tasks表的数量是有限的,例如20个。每个任务都位于Tasks表中,并具有一些通用的特性。用户可以注册一个任务,但随后可以使用TaskInstance表为该任务分配独特的质量。TaskInstance变量包括:

  • TkInstanceInfoA, TkInstanceInfoB, TkInstanceInfoC, TkInstanceInfoD允许各种描述等
  • TkInstanceSide指示任务是在右侧,左侧还是没有侧(L, R或null)完成
  • fkTkID告诉我们哪个任务是TaskInstance的父任务
  • fkStID告诉我们哪个学生是TaskInstance的父级

数据库:

Students
1.) StID
2.) StNameFirst
3.) StNameLast
4.) StGender
5.) StPasscode
6.) fkProID
Tasks
1.) TkID
2.) TkSide (the task by nature has a side?: Y or N) 
3.) TkImgML
4.) TkImgMR 
5.) TkImgMC 
6.) TkImgFL 
7.) TkImgFR
8.) TkImgFC
9.) TkTitleSci
10.) TkTitleCom
11.) TkDesc
TaskInstance
1.) TkInstID
2.) TkInstSide (which side is the task?: L, R or null)
3.) TkInstInfoA
4.) TkInstInfoB
5.) TkInstInfoC
6.) TkInstInfoD
7.) TkInstCustomTitleSci
8.) TkInstCustomTitleCom
9.) TkInstCustomDesc
10.) TkInstOrder
11.) fkTkID
12.) fkStID
MySQL:

更新:2013年4月16日12:03 pm EST:我有SELECT和SELECT CASE颠倒,缺少逗号。现在更正,但仍然打破:

$CurrentStID = 1; // known previously
$CurrentStGender = M; // known previously
SELECT *, 
   CASE StGender
       WHEN 'M' THEN
           CASE IFNULL(TkInstSide, 'C')
                WHEN 'L' THEN TkImgML
                WHEN 'R' THEN TkImgMR
                ELSE TkImgMC
           END
       WHEN 'F' THEN
           CASE IFNULL(TkInstSide, 'C')
                WHEN 'L' THEN TkImgFL
                WHEN 'R' THEN TkImgFR
                ELSE TkImgFC
           END
   END TkImgCase,
   CASE StTitlePref
       WHEN 'Common' THEN
           CASE WHEN TkInstCustomTitleCom IS NULL 
                THEN TkTitleCom 
                ELSE TkInstCustomTitleCom
           END
       WHEN 'Scientific' THEN
           CASE WHEN TkInstCustomTitleSci IS NULL 
                THEN TkTitleSci 
                ELSE TkInstCustomTitleSci
           END
   END TkTitleCase
FROM TaskInstance 
LEFT JOIN Tasks ON fkTkID = TkID 
LEFT JOIN Students ON fkStID = StID
WHERE fkStID = $CurrentStID 
ORDER BY TkInstOrder

打印:

1。)检查自定义标题和描述,否则使用标准:

更新:2013年4月16日上午11:52 EST:我一直挂在自定义标题。我的调整是否有效?它似乎失败了。

if ($row['StTitlePref'] == "Common") && (strlen(trim($row['TkInstCustomTitleCom'])) > 0) { $TkTitle = $row['TkInstCustomTitleCom'] } // will be default or custom
else if ($row['StTitlePref'] == "Scientific") && (strlen(trim($row['TkInstCustomTitleSci']) > 0) { $TkTitle = $row['TkInstCustomTitleSci'] } // will be default or custom

2。)从6张图片中选择1张:

是否可以使用MySQL使用性别来消除6个图像中的3个,然后再使用PHP if/then来选择剩下的3个图像中的1个?

如果Student 's Gender (StGender)是male,并且Task有一个side (TkSide),则显示正确的图像:如果是L-side (TkInstanceSide),则显示L male image (TkImgML);如果是R侧(TkInstanceSide),则显示R男像(TkImgMR)。如果学生的性别(StGender)是男性,并且任务没有侧面(TkSide)[同时TkInstanceSide为null],则显示中心男性图像(TkImgMC)。

如果Student 's Gender (StGender)是女性,并且Task有一侧(TkSide),则显示正确的图像:如果是L侧(TkInstanceSide),则显示L女性图像(TkImgFL);如果是R侧(TkInstanceSide),则显示R女性图像(TkImgFR)。如果学生的性别(StGender)是女性,并且任务没有侧面(TkSide)[同时TkInstanceSide为null],则显示中心女性图像(TkImgFC)。

3)。显示与此实例相关的其他信息:

显示这4个变量:TkInstanceInfoA、TkInstanceInfoB、TkInstanceInfoC、TkInstanceInfoD。

所以,最终是这样的:

echo ‘<p>’ . $TkTitleCom . ‘<br>’;  // show either standard title or custom title
echo $TkDesc . ‘<br>’; // show either standard description or custom description
echo $TkInstanceInfoA . ‘<br>’;
echo $TkInstanceInfoB . ‘<br>’;
echo $TkInstanceInfoC . ‘<br>’;
echo $TkInstanceInfoD . ‘<br>’;
echo $CorrectImg  . ‘</p>’;  // show either TkImgML, TkImgMR, TkImgMC, TkImgFL, TkImgFR or TkImgFC

4/18/2013:后续问题(类似的)

亲爱的Barmar:非常感谢你的帮助。如果您有时间,我有一个后续问题。我有一个显示页面,我只是试图从任务表拉(而不是像以前一样从TaskInstance表)。

我知道$CurrentStGender和$CurrentStTitlePref从以前的查询。我仍然希望使用CASE语句选择正确的图像(6个中的1个)和正确的标题首选项。我有一个艰难的时间试图找出如何喂养我的两个已知变量的SQL。你能帮忙吗?

// echo $CurrentStGender . ', ' . $CurrentStTitlePref;
if ($result = $mysqli->query("
SELECT *, 
   CASE CurrentStGender
       WHEN 'M' THEN
           CASE WHEN TkSide == 'Y' THEN TkImgML /* if task can be done on a side, show just the L-side
                ELSE TkImgMC
           END
       WHEN 'F' THEN
           CASE WHEN TkSide == 'Y' THEN TkImgFL /* if task can be done on a side, show just the L-side
                ELSE TkImgFC
           END
   END TkImgCase,
   CASE StTitlePref
       WHEN 'Common' THEN TkTitleCom 
           END
       WHEN 'Scientific' THEN TkTitleSci 
           END
   END TkTitleCase
FROM Tasks

您可以在SQL:

中选择基于性别和侧面的图像。
SELECT *, 
       CASE StGender
           WHEN 'M' THEN
               CASE IFNULL(TkSide, 'C')
                    WHEN 'L' THEN TkImgML
                    WHEN 'R' THEN TkImgMR
                    ELSE TkImgMC
               END
           WHEN 'F' THEN
               CASE IFNULL(TkSide, 'C')
                    WHEN 'L' THEN TkImgFL
                    WHEN 'R' THEN TkImgFR
                    ELSE TkImgFC
               END
       END TkImg
FROM TaskInstance 
LEFT JOIN Tasks ON fkTkID = TkID 
LEFT JOIN Students ON fkStID = StID
WHERE fkStID = $CurrentStID 
ORDER BY TkInstOrder

后续回答:

有两种方法可以做到这一点。一种方法是保持当前的两层CASE结构,但将列名替换为用PHP变量填充的文字(在CASE语句中允许任何表达式,因此文字与列名一样好):

CASE '$CurrentStGender'
   WHEN 'M' THEN ...
   WHEN 'F' THEN ...
END TkImgCase,
CASE '$CurrentStTitlePref'
    WHEN 'Common' THEN TkTitleCom 
        END
    WHEN 'Scientific' THEN TkTitleSci 
        END
END TkTitleCase

另一个利用了列遵循命名约定的事实,因此您可以直接插入到列名中:

$titleAbbrev = substr($CurrentStTitlePref, 0, 3);
if ($result = $mysqli->query("
  SELECT *,     
     CASE WHEN TkSide == 'Y' THEN TkImg{$CurrentStGender}L
          ELSE TkImg{$CurrentStGender}C
     END TkImgCase,
     TkTitle{$titleAbbrev} TkTitleCase
  FROM Tasks");

(1) Print

if (strlen(trim($TkInstCustomTitleCom)) > 0) $tkTitleCom = $tkInstCustomTitleCom;
echo $tkTitleCom; // will be default or custom

(2)打印

试试这个代替if ... else;括号内的表达式称为ternary operator,第2行中的表达式为variable variable:

$image = "TkImg" . $StGender . ($TkSide=='Y'?$TkInstanceSide:'C');
$imagename = $$image; // now $imagename contains the content of e.g. $TkImgMC 

查看它的工作情况:http://codepad.viper-7.com/abpxbU

SQL

$sql = <<<SQL
SELECT *
FROM TaskInstance
LEFT JOIN Tasks ON fkTkID = TkID
WHERE fkStID = :stID
ORDER BY TkInstOrder 
SQL;

相同但不同:

$sql = "SELECT * FROM TaskInstance LEFT JOIN Tasks ON fkTkID = TkID WHERE fkStID = :stID ORDER BY TkInstOrder"; 

:stID为参数,查询为参数化查询。它对sql注入是安全的。您将使用PDO函数而不是mysql_*(已弃用)。