MSSQL内外连接(INNER JOIN)语句详解

转载自:http://www.jb51.net/article/4848.htm

在之前,我对MSSQL中的内连接和外连接所得出的数据集不是很清楚。这几天重新温习了一下SQL的书本,现在的思路应该是很清楚了,现在把自己的理解发出来给大家温习下。希望和我一样对SQL的连接语句不太理解的朋友能够有所帮助。(发这么菜的教程,各位大大们别笑话偶了,呵:D )

有两个表A和表B。

表A结构如下:
Aid:int;标识种子,主键,自增ID
Aname:varchar

数据情况,即用select * from A出来的记录情况如下图1所示:

图1:A表数据

表B结构如下:
Bid:int;标识种子,主键,自增ID
Bnameid:int

数据情况,即用select * from B出来的记录情况如下图2所示:


图2:B表数据

为了把Bid和Aid加以区分,不让大家有误解,所以把Bid的起始种子设置为100。
有SQL基本知识的人都知道,两个表要做连接,就必须有个连接字段,从上表中的数据可以看出,在A表中的Aid和B表中的Bnameid就是两个连接字段。
下图3说明了连接的所有记录集之间的关系:

图3:连接关系图

现在我们对内连接和外连接一一讲解。
1.内连接:利用内连接可获取两表的公共部分的记录,即图3的记录集C
语句如下:Select * from A JOIN B ON A.Aid=B.Bnameid
运行结果如下图4所示:

图4:内连接数据

其实select * from A,B where A.Aid=B.Bnameid与Select * from A JOIN B ON A.Aid=B.Bnameid的运行结果是一样的。
2.外连接:外连接分为两种,一种是左连接(Left JOIN)和右连接(Right JOIN)
(1)左连接(Left JOIN):即图3公共部分记录集C+表A记录集A1。
语句如下:select * from A Left JOIN B ON A.Aid=B.Bnameid
运行结果如下图5所示:


图5:左连接数据

说明:
在语句中,A在B的左边,并且是Left Join,所以其运算方式为:A左连接B的记录=图3公共部分记录集C+表A记录集A1
在图3中即记录集C中的存在的Aid为:2 3 6 7 8
图1中即表A所有记录集A中存在的Aid为:1 2 3 4 5 6 7 8 9
表A记录集A1中存在的Aid=(图1中即A表中所有Aid)-(图3中即记录集C中存在的Aid),最终得出为:1 4 5 9
由此得出图5中A左连接B的记录=图3公共部分记录集C+表A记录集A1,
最终得出的结果图5中可以看出Bnameid及Bid非NULL的记录都为图3公共部分记录集C中的记录;Bnameid及Bid为NULL的Aid为1 4 5 9的四笔记录就是表A记录集A1中存在的Aid。

(2)右连接(Right JOIN):即图3公共部分记录集C+表B记录集B1。
语句如下:select * from A Right JOIN B ON A.Aid=B.Bnameid
运行结果如下图6所示:


图6:右连接数据

说明:
在语句中,A在B的左边,并且是Right Join,所以其运算方式为:A右连接B的记录=图3公共部分记录集C+表B记录集B1
在图3中即记录集C中的存在的Aid为:2 3 6 7 8
图2中即表B所有记录集B中存在的Bnameid为:2 3 6 7 8 11
表B记录集B1中存在的Bnameid=(图2中即B表中所有Bnameid)-(图3中即记录集C中存在的Aid),最终得出为:11
由此得出图6中A右连接B的记录=图3公共部分记录集C+表B记录集B1,
最终得出的结果图6中可以看出Aid及Aname非NULL的记录都为图3公共部分记录集C中的记录;Aid及Aname为NULL的Aid为11的记录就是表B记录集B1中存在的Bnameid。

总结:

通过上面的运算解说,相信很多人已经想到,上面的情况(包括图3的关系图)说明的都只是A在B的左边的情况,
以下语句B在A的右边的又会出现什么情况呢??
select * from B Left JOIN A ON A.Aid=B.Bnameid
select * from B Right JOIN A ON A.Aid=B.Bnameid

其实对图3左右翻转一下就可以得出以下结论:
select * from B Left JOIN A ON A.Aid=B.Bnameid和select * from A Right JOIN B ON A.Aid=B.Bnameid所得出的记录集是一样的

select * from B Right JOIN A ON A.Aid=B.Bnameid和select * from A Left JOIN B ON A.Aid=B.Bnameid所得出的记录集也是一样的。

第一次写类似教程的贴子,希望和我一样对SQL的连接语句不太理解的朋友能够有所帮助。谢谢大家支持。

焦虑

2012年6月9日 15:53:04,写下这篇文章是为了让我自己更好的认识自己。

2012年5月1日,公司放了三天假期,本来之前的每个周末我都会找个附近的地方、景点逛一逛看一看,以便缓解自己平常的工作压力,也是享受生活的一部分。但是从五一开始,情况变了,基本上过了4-5个周末没有出去了,这阵子的工作效率也是极度下降,整天想着换工作,提高工资,业余时间能够搞点兼职赚外快。本来是放松的时间,用来思考赚外快(只是思考,却为行动)。

生活完全被打乱,其实从今年过完年之后,自己的PHP代码上面已经没有更多突破性的东西去让我成长,也就是说整天在公司是靠着经验在吃饭。简单点来讲,我的头脑里面想的是钱,但实际上,想的这些乱七八糟的东西都是完全没有用的东西,赚个P钱。

睡不好觉,昨天在我的QQ空间写了一篇日志《坚持每天锻炼》,内容如下:
从6.8-9.8 这三个月,坚持隔天上一次白云山,其它时间跑步(可选),以此记录。

希望在锻炼身体的过程中,我能想清楚自己该努力的方向和跳过生活中的陷阱,保持精神状态第一,努力朝正确的方向第二。

主从数据库的IP地址更换时,用到的自动替换功能

主从数据库的IP地址更换时,用到的自动替换功能
这也是工作中遇到的,自己想办法做的自动替换功能,节约很多的时间,办公中能自动的东西就尽量去自动化,节约时间,提高效率。

<?php 
/*
 * 在文件配置中大多数的数据库链接定义的格式是define("TEST_MASTER_DB_HOST", "192.168.1.1"); 现在要替换成define("TEST_MASTER_DB_HOST", "192.168.1.10");
 * 该PHP代码就是用来自动替换Ip地址
 */
$dbNameArr      =    array("testDb",'newDb');
$prefixArr[]    =    array('_MASTER_','_SLAVE_');
$dirPath        =    'D:/wamp/www/test/';
$pathArr        =    array();
$replaceArr     =    array();
// replace start ====================================================================
foreach ($prefixArr[0] as $v)
{
    foreach ($dbNameArr as $val)
    {
        $dbNameUp        =    strtoupper($val);
        $val1            =    'define("'.$dbNameUp.$v.'DB_HOST", "192.168.65.1");';
        $val2            =    'define("'.$dbNameUp.$v.'DB_HOST", "192.168.65.2");';
        $val3            =    'define("'.$dbNameUp.$v.'DB_HOST", "192.168.85.3");';
        $replaceArr[]    =    array($val1,$val3);
        $replaceArr[]    =    array($val2,$val3);
    }
}
foreach ($prefixArr[1] as $v)
{
    foreach ($dbNameArr as $val)
    {
        $dbNameUp        =    strtoupper($val);
        $val1            =    'define("'.$dbNameUp.$v.'DB_HOST", "192.168.65.10");';
        $val2            =    'define("'.$dbNameUp.$v.'DB_HOST", "192.168.65.20");';
        $val3            =    'define("'.$dbNameUp.$v.'DB_HOST", "192.168.85.30");';
        $replaceArr[]    =    array($val1,$val3);
        $replaceArr[]    =    array($val2,$val3);
    }
}
$pathArr    =    file_list($dirPath);
//print_r($pathArr);exit;
 
foreach ($pathArr as $filePath)
{
    replace($filePath,$replaceArr);
}
// replace end ====================================================================
 
function replace($filePath,$replaceArr)
{
    $oldData    =    file_get_contents($filePath);
    foreach ($replaceArr as $v)
    {
        $oldData    =    str_replace($v[0],$v[1],$oldData);
    }
    file_put_contents($filePath,$oldData);
}
function file_list($path)
{
    global $pathArr;
    if ($handle = opendir($path))
    {
        while (false !== ($file = readdir($handle)))
        {
            if ($file != "." && $file != "..")
            {
                //echo $path.": ".$file."<br>";
                if (is_dir($path."/".$file))
                {
                    file_list($path."/".$file);
                }
                else
                {
                    $pathArr[]    = $path."/".$file;
                }
            }
        }
    }
    return $pathArr;
}
?>