SQL - 为什么这不起作用?

时间:2010-10-12 18:21:28

标签: sql mysql

以下脚本允许您创建数据库并使用我的问题的必要数据填充它:

# 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;

有人可以帮我理解为什么以下查询无法获取active = 1,published = 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
            )
        )
    )

2 个答案:

答案 0 :(得分: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表中的所有记录产生一个笛卡尔联接,其中资源表的active,published和resourcePublic值都是1。

如果资源表的活动和已发布值都是1,但resourcePublic不是1,我希望内部联接到resourceOrganization表上的organization_id为2的记录,永远是1或当前日期为午夜位于开始和结束日期时间值之间。我注意到结束日期时间默认为0000-00-00 00:00:00。

排除活动或已发布值不为1的记录,因此资源未报告的明显原因是resourcePublic值不是1,

  • organization_id 2或
  • 没有相应的resourceOrganization记录
  • 相应的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
           )
     )

答案 1 :(得分:0)

Mark,Tony,Leslie等等,感谢您的反馈,但我设法避开了这个问题!

如果resourceOrganization表中没有记录,我发现where子句会导致false。这意味着即使资源表具有active,published和resourcePublic都为1的记录,如果resourceOrganization表中没有数据,where子句也会导致false。我真的不明白为什么会这样,但是现在我发现了这个,我在我的Java代码中添加了一些逻辑来构建查询字符串,具体取决于是否是resourceOrganization表中的记录。

在任何情况下,是否有人对此行为有任何解释?