2010-10-12 108 views
0

下面的腳本允許你創建的數據庫,並與我的問題所需的數據填充它:SQL - 爲什麼這不起作用?

# HeidiSQL Dump 
# 
# -------------------------------------------------------- 
# Host:     127.0.0.1 
# Database:    blueskylearning 
# Server version:  5.1.22-rc-community 
# Server OS:   Win32 
# Target-Compatibility: MySQL 5.0 
# Extended INSERTs:  Y 
# max_allowed_packet: 1048576 
# HeidiSQL version:  3.0 Revision: 572 
# -------------------------------------------------------- 

/*!40100 SET CHARACTER SET latin1*/; 


# 
# Database structure for database 'windowsLinuxProblem' 
# 

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `windowsLinuxProblem` /*!40100 DEFAULT CHARACTER SET utf8 */; 

USE `windowsLinuxProblem`; 


# 
# Table structure for table 'organization' 
# 

CREATE TABLE /*!32312 IF NOT EXISTS*/ `organization` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(200) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 



# 
# Dumping data for table 'organization' 
# 

/*!40000 ALTER TABLE `organization` DISABLE KEYS*/; 
LOCK TABLES `organization` WRITE; 
REPLACE INTO `organization` (`id`, `name`) VALUES 
(1,'Org1'); 
UNLOCK TABLES; 
/*!40000 ALTER TABLE `organization` ENABLE KEYS*/; 


# 
# Table structure for table 'resource' 
# 

CREATE TABLE /*!32312 IF NOT EXISTS*/ `resource` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `title` varchar(100) NOT NULL, 
    `resourcePublic` tinyint(4) NOT NULL, 
    `active` tinyint(4) NOT NULL, 
    `published` tinyint(4) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=534 DEFAULT CHARSET=utf8; 



# 
# Dumping data for table 'resource' 
# 

/*!40000 ALTER TABLE `resource` DISABLE KEYS*/; 
LOCK TABLES `resource` WRITE; 
REPLACE INTO `resource` (`id`, `title`, `resourcePublic`, `active`, `published`) VALUES 
    (1,'Title number 1',1,1,1), 
    (2,'Title number 2',1,1,1), 
    (3,'Title number 3',1,1,1), 
    (4,'Title number 4',1,1,1), 
    (5,'Title number 5',1,1,1), 
    (6,'Title number 6',1,1,1); 
UNLOCK TABLES; 
/*!40000 ALTER TABLE `resource` ENABLE KEYS*/; 


# 
# Table structure for table 'resourceorganization' 
# 

CREATE TABLE /*!32312 IF NOT EXISTS*/ `resourceorganization` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `resource_id` int(11) NOT NULL, 
    `organization_id` int(11) NOT NULL, 
    `forever` tinyint(4) NOT NULL, 
    `startDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `endDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`id`), 
    KEY `resource_id` (`resource_id`), 
    KEY `organization_id` (`organization_id`), 
    CONSTRAINT `resourceorganization_ibfk_1` FOREIGN KEY (`resource_id`) REFERENCES `resource` (`id`), 
    CONSTRAINT `resourceorganization_ibfk_2` FOREIGN KEY (`organization_id`) REFERENCES `organization` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=115 DEFAULT CHARSET=utf8; 

有人能幫助我理解了爲什麼下面的查詢不主動獲取所有資源= 1,公佈= 1,resourcePublic = 1

查詢:

select * 
from 
    resource resource0_, 
    resourceOrganization resourceor1_ 
where 
    resource0_.active=1 
    and resource0_.published=1 
    and (
     resource0_.resourcePublic=1 
     or resourceor1_.resource_id=resource0_.id 
     and resourceor1_.organization_id=2 
     and (
      resourceor1_.resource_id=resource0_.id 
      and resourceor1_.forever=1 
      or resourceor1_.resource_id=resource0_.id 
      and (
       current_date between resourceor1_.startDate and resourceor1_.endDate 
      ) 
     ) 
    ) 
+0

我從數據庫中提取資源,在這些資源中他們處於活動狀態,發佈狀態以及公開或與組織共享,以便共享永遠或在兩個日期之間。 – 2010-10-12 18:31:49

+0

資源組織表沒有數據? – Leslie 2010-10-12 18:32:33

+0

如果資源組織表沒有任何數據,我會認爲where子句的一部分將是假的 – 2010-10-12 19:08:31

回答

3

既然這樣,該查詢應簡化到:

select * 
from 
    resource resource0_, 
    resourceOrganization resourceor1_ 
where 
    resource0_.active=1 and 
    resource0_.published=1 and 
    (resource0_.resourcePublic=1 or 
     (resourceor1_.resource_id=resource0_.id and 
     resourceor1_.organization_id=2 and 
      (resourceor1_.forever=1 or 
      current_date between resourceor1_.startDate and resourceor1_.endDate 
      ) 
     ) 
    ) 

我希望它可以生成一個笛卡兒加入對resourceOrganization表,所有記錄在資源表的活動,出版和resourcePublic值都是1

在資源表的活動並發表值均爲1 ,但resourcePublic不是1,我期望內部聯接記錄在organization_id爲2的resourceOrganization表上,並且永遠是1或者在午夜的當前日期在開始和結束日期時間值之間。我注意到結束日期時間默認爲0000-00-00 00:00:00。因此

排除其中主動或公佈值不爲1,對於不被報告的資源的明顯的原因記錄是該resourcePublic值不是1,或者:

  • 沒有相應的resource_organization記錄爲organization_id 2或
  • 相應的resourceOrganization記錄具有永久值不是1 在午夜的當前日期不在開始和結束日期時間值之間。

的日期範圍出現的錯誤排除的記錄的最可能的來源 - 午夜後的當天輸入的記錄將開始日期時間值,因此將被排除在外,而沒有指定結束日期的記錄將默認爲0000- 00-00 00:00:00,因此也將被排除在外。

因此,我建議重寫查詢是這樣的:

select * 
from resource r 
left join resourceOrganization ro 
on r.id = ro.resource_id and ro.organization_id = 2 
where 
    r.active=1 and 
    r.published=1 and 
    (r.resourcePublic=1 or 
    ro.forever=1 or 
    now() between ro.startDate and 
      (case where ro.endDate = '0000-00-00 00:00:00' 
       then now() 
       else ro.endDate end 
      ) 
    ) 
+0

+1:很好,完整,回答。我想補充說,刪除[forever]列並將[endDate]默認值更改爲「9999-12-31 23:59:59」將更加簡化查詢。 – Tony 2010-10-13 13:20:13

0

馬克,託尼,萊斯利和所有的,感謝您的反饋,但我設法迴避的問題!

我發現如果resourceOrganization表中沒有記錄,where子句將導致false。這意味着,即使資源表具有active,published和resourcePublic都爲1的記錄,如果resourceOrganization表中沒有數據,where子句的結果爲false。我真的不明白爲什麼會出現這種情況,但現在我發現了這一點,我在Java代碼中添加了一些邏輯來構建查詢字符串,具體取決於resourceOrganization表中是否有記錄。

無論如何,有沒有人有任何解釋這種行爲?

+1

正如Mark所說的,你原來的查詢是將[resource]的笛卡爾連接執行到[resourceOrganization],這是當你將一個表的每一行連接到另一個表的每一行時。如果其中一個表中沒有記錄,則無法執行此類型的聯接。您將不得不更改查詢以使用LEFT JOIN。 – Tony 2010-10-14 09:29:32

+0

忘了工作全面,直到你學會了解什麼是錯誤的,你會繼續犯同樣的錯誤 – 2010-10-14 12:31:16

+0

馬克,託尼和KM,非常欣賞我的方法 – 2010-10-15 15:13:46