标题可能总结了我的问题,但要明确的是,我特别考虑的是 RDB。
我无意这样做,我只是很好奇,并且在尝试谷歌搜索时没有找到明确的答案。
如果它是或不是真的,可以解释原因吗?(如果不是太大的要求)
感谢任何愿意分享对此的见解的人。
我正在使用一个小模型,并且正在为一个简单的问题而苦苦挣扎。
我应该如何存储地址/邮件/电话列表并选择一个作为委托人?
我现在想的例子。
地址实体:
个人实体:
这是我在 EF Core 中创建的实体:
public class Person
{
public Person()
{
Addresses = new HashSet<Address>();
PhoneNumbers = new HashSet<PhoneNumber>();
Emails = new HashSet<Email>();
}
[StringLength(100)]
public string Firstname { get; set; } = null!;
[StringLength(300)]
public string Lastname { get; set; } = null!;
public Gender Gender { get; set; }
public DateTime BirthDate { get; set; }
public Guid? MainAddressId { get; set; }
public Address MainAddress { get; set; } = null!;
public virtual ICollection<Address> Addresses { get; internal set; }
}
但这对我来说看起来很脏。
例如,我们有一个问题是要找到表中薪水第二高的员工。这是我的桌子
id name dept salary
1 Ram HR 10000
2 Amrit MRKT 20000
3 Ravi HR 30000
4 Nitin MRKT 40000
5 Varun IT 50000
然后我会写一个这样的子查询。
select e_name,salary from employee
where salary = (select max(salary) from employee
where salary <> (select max(salary) from employee));
我会像这样使用限制和偏移:
select e_name, salary from employee order by salary desc limit 1 offset 1;
以下哪项会更有效率?为什么?
我有应该存储在 MSSQL 服务器中的整数到期日的收益率曲线数据。
目前,数据按货币存储在 CSV 文件中,格式如下:
date, 1y, 2y, 3y, ...
08/12/2020, 0.4, 0.5, 0.6, ...
我想知道桌子的最佳选择是什么。
当前数据可以直接转换为带有列的表:
+------------+------+------+------+------+
| date | 1y | 2y | 3y | ... |
+------------+------+------+------+------+
| 08/12/2020 | 0.4 | 0.5 | 0.6 | ... |
+------------+------+------+------+------+
但是,我也可以像这样存储它:
+------------+-----------+-----------+--------+
| date | currency | maturity | value |
+------------+-----------+-----------+--------+
| 08/12/2020 | "EUR" | 1 | 0.4 |
| 08/12/2020 | "EUR" | 2 | 0.5 |
| 08/12/2020 | "EUR" | 3 | 0.6 |
+------------+-----------+-----------+--------+
显然,第二种方法将比第一种方法占用更多空间,但我会看到我不会限制到期值的优势,以防将来它应该更改为非整数值或到期有一个专栏呢。
两种桌子设计哪个更好?还有其他更适合的设计吗?
我找到了我 2011 年的一些旧笔记,并且我还重新阅读了 @lukas-eder 的优秀文章10 Cool SQL Optimisations That do not Depending the Cost Model。所以我想我会再记笔记。场景很简单Fiddle
create table emp (
emp_no int not null primary key,
title varchar(10) not null,
salary int not null,
check (emp_no > 0),
check (title in ('BOSS','WORK'))
);
insert into emp with recursive t (n) as (
values (1)
union all
select n+1 from t where n+1 < 1000
) select n, case when mod(n,10) = 0 then 'BOSS' else 'WORK' end,
case when mod(n,10) = 0 then 110 else 0 end + mod(n,90)
from t;
现在,给定规则:
(TITLE = BOSS) implies (SALARY > 100)
和
(TITLE = WORK) implies (SALARY <= 100)
可以实现为:
-- (TITLE = BOSS) => (SALARY > 100)
alter table emp add constraint cc1
CHECK ( (title <> 'BOSS' OR salary > 100) );
-- (TITLE = WORK) => (SALARY <= 100)
alter table emp add constraint cc2
CHECK ( (title <> 'WORK' OR salary <= 100) );
和查询:
select *
from emp
where title = 'BOSS' and salary <= 100
DBMS 能否发现矛盾,并在不接触数据的情况下返回空结果集?
Let A = ( title = ’BOSS’ ), B = ( salary > 100 )
select * from emp where (A ^ ~B)
select * from emp where (A ^ ~B) ^ (~A v B) # by cc1
select * from emp where (A ^ ~B ^ ~A) v (A ^ ~B ^ B)
select * from emp where (FALSE ^ ~B) v (A ^ FALSE)
select * from emp where (FALSE) v (FALSE)
select * from emp where (FALSE)
我试过 Postgres 13(见上面的小提琴)
Seq Scan on emp (cost=0.00..26.50 rows=2 width=46) (actual time=0.134..0.134 rows=0 loops=1)
Filter: ((salary <= 100) AND ((title)::text = 'BOSS'::text))
Rows Removed by Filter: 999
Planning Time: 0.312 ms
Execution Time: 0.149 ms
和 DB2 11.5.4.0:
Optimized Statement:
-------------------
SELECT
Q1.EMP_NO AS "EMP_NO",
Q1.TITLE AS "TITLE",
Q1.SALARY AS "SALARY"
FROM
DB2INST1.EMP AS Q1
WHERE
(Q1.SALARY <= 100) AND
(Q1.TITLE = 'BOSS')
Access Plan:
-----------
Total Cost: 51.8267
Query Degree: 1
Rows
RETURN
( 1)
Cost
I/O
|
90.2441
TBSCAN
( 2)
51.8267
4
|
999
TABLE: DB2INST1
EMP
Q1
但两者都没有这样做。任何其他可以发现矛盾并采取行动的 DBMS?这当然比现实世界的问题更有趣,但仍然如此。
编辑:@federico-razzoli 在他的回答中建议的约束也不起作用:
alter table emp add constraint cc1
check ((title = 'BOSS' and salary > 100) or
(title = 'WORK' AND salary <= 100));
并且相同的查询仍然会导致表访问
Rows
RETURN
( 1)
Cost
I/O
|
90.2441
TBSCAN
( 2)
51.8267
4
|
999
表:DB2INST1 EMP Q1
给定第一个表
CREATE TABLE table1 (
column1 INTEGER,
column2 TEXT,
PRIMARY KEY (column1, column2));
SQL 是否有一种惯用的方式来约束column3
第二个表
CREATE TABLE table2 (
column3 INTEGER,
column4 TEXT,
PRIMARY KEY (column3, column4));
这样column3
⊆ column1
?
我目前的解决方案是这个kludge:
CREATE TABLE table0 (
column0 SERIAL PRIMARY KEY);
CREATE TABLE table1 (
column1 INTEGER REFERENCES table0 (column0),
column2 TEXT,
PRIMARY KEY (column1, column2));
CREATE TABLE table2 (
column3 INTEGER REFERENCES table0 (column0),
column4 TEXT,
PRIMARY KEY (column3, column4));
我学到了外键不能只引用复合主键的一个值的艰难方法:https ://stackoverflow.com/questions/3996774/foreign-key-relationship-with-composite-primary-keys-in-sql -服务器-2005。
如果这很重要,我正在使用 PostgreSQL。
一条评论建议我添加一个具体的例子。
该表table1
包含别名。多人可以被命名为“Jane Doe”,任何一个“Jane Doe”也可以被称为“Jane Smith”和“Jane1990”。每个人都由 中的数字唯一标识column1
。任一列都可以有重复项,但不允许重复行。
该表table2
列出了 中的人出版的书籍table1
,但table1
可以包括从未出版过书籍的人,等等column3
⊆ column1
。再次不允许重复行。