PostgreSQL战斗机的任务和解决方案


向所有SQL爱好者致以问候!

在Internet上,我很少见到涉及与SQL数据处理相关的不同工作点和细节的文章。
当您一次可以从一篇文章中学到很多东西时,即使是一般而言,我也喜欢。
因此,我决定写我的文章,其中包含各种任务和答案以及对它们的解释。
适合那些已经熟练掌握所有基本技能并想要进一步发展的人。

提供的答案适用于PostgreSQL大多数任务都适用于其他DBMS ,但是结果和解决方案可能有所不同。出现差异之处甚至很有趣)

打开扰流板之前, 请尝试回答自己

走吧


我将尝试用星号标记纯粹用于PostgreSQL的内容(这种情况并不多)

1.关于数值运算的一些知识


1.1这些要求会得到满足吗? 他们将返回什么结果?

-- )     SELECT 3/2; -- ) SELECT min('- '::TEXT), avg('- '::TEXT); -- )*      FALSE,     ? SELECT 7.2 = (3.8::FLOAT + 3.4) -- ) SELECT (20/25)*25.0; 


1.1的答案
A)答案: 1
仅显示整个部分,因为 该操作使用整数。 通常在其他语言中找到。

B)回答:请求将不会执行

avg将给出一个错误,因为 仅接受数字和时间间隔*

但是,可以对文本数据执行min / max函数(根据数据库中的字母排序)。
有时当您需要至少查看GROUP BY中未列出的列时,这可能会很有用
或者当您需要对数字应用字母排序时,其中'10'<'2'

B)答案:

可能看起来很奇怪,但这是可以接受的 ,因为 这是代表某些浮点数的计算机的功能;数字可以采用7.1(9)的形式
我记得曾经很长时间不知如何处理请求。

D)回答: 0 。 问题是括号中的表达式将= 0

SELECT(20 / 25.0)* 25会更正确地工作


1.2给定表“ table_2 ”(单列“ value ”(INTEGER))由以下5行组成:
价值
5
5
空值
5
5

什么结果将返回查询:
 SELECT (avg(value)*count(*)) - sum(value) FROM table_2; 

答案选项
  • -4
  • 0
  • 空值
  • 5
  • 这将导致错误,因为 未指定GROUP BY
  • 没有列出


答案1.2
答案: 5

应用于特定列的聚合函数将忽略NULL ,但是count (*)将对所有行进行计数
5 * 5-20


2.一般问题


2.1在什么情况下查询不能返回表的所有内容? ( parent_id INTEGER,表中填充了各种数据)

  SELECT * FROM any_table WHERE parent_id = parent_id; 

以下请求的行为如何? 它将输出什么数据? * PostgreSQL

  SELECT * FROM any_table WHERE parent_id IS NOT DISTINCT FROM parent_id; 

答案2.1
第一个查询将显示所有条目,但parent_idNULL的条目除外

第二个查询将显示所有表条目。 IS DISTINCT FROM在逻辑上类似于运算符!=其中NULL等于NULL
逻辑上看并不一致

2.2。 请求的结果是什么?

 -- ) SELECT * FROM ( SELECT 1 UNION ALL SELECT 1 ) x(y) UNION ( SELECT 2 UNION ALL SELECT 2 ); 

回复2.2
结果将是2行,其值为12UNION将删除结果选择中的所有重复项,而不仅仅是两个联接表之间的重复项。 我注意到这对每个人都不是显而易见的。

2.3编写查询以显示明天的日期。

回答2.3
 SELECT CAST((now()+ INTERVAL '1 DAY') AS DATE) 

并非每个人都经常使用日期,但值得掌握一些最低要求
* Postgres解决方案,但我认为其他DBMS差别不大

如果您不喜欢使用日期,建议您尝试一下
例如:
-将DAY替换为(周,月,年等)
-用-9000代替+1
-将DATE替换为TIME
-删除CAST
-现在只留下()


并且,受一些结果的启发,请阅读MANUAL ,其中详细介绍了所有主题


2.4 UPDATEDELETEINSERTMERGE 语句旨在处理表中的数据。 SELECT ..执行是否“安全”? 任何查询都会影响表中的数据吗?
回答2.4
这个问题似乎很原始,但是...

在学习SQL的一开始,我认为该语句只能显示数据,但是:

SELECT能够锁定表以进行更改(BEGIN; SELECT ... FOR UPDATE)*
SELECT能够调用几乎可以执行任何操作的函数。

初学者需要立即理解这一点,而不是在生产服务器上完成“少量信息性”请求之后


3.仅PostgreSQL


3.1描述在SQL对话框中执行此查询时会发生什么:

 SELECT * INTO wtf FROM pg_stat_activity; 

回复3.1
通常,在plpgsql函数中使用SELECT INTO将值写入变量。

在plpgsql之外,该命令的效果将类似于以下查询:

 CREATE TABLE wtf AS SELECT * FROM pg_stat_activity; 


3.2此“简单”请求将显示什么

 SELECT wtf_ FROM pg_stat_activity AS wtf_ ; 

回复3.2
pg_stat_activity数据库中活动进程的系统视图(VIEW)。

该查询的特殊性是将显示具有类型pg_stat_activity的行(ROW)的一列(或另一表)。 您需要对编写函数的人早一点了解这一点,您可以在手册中阅读更多内容
添加该问题的原因是,初学者很容易会错误地得到这样的结果,并且不了解问题所在

4.处理文本。 正则表达式


我认为您不仅需要能够构建查询,而且还必须以正确的方式呈现结果。
正则表达式是一个单独的庞大主题,包含许多优质文章。 因此,我将仅显示示例,而没有详细说明。

4.1。 假设存在一个带有文本列“ X ”和许多不同行的表“ table_5 ”。 什么查询可以获取每行的最后10个字符?

回复4.1
SQL使您可以针对同一问题提出很多解决方案,例如:
想到的最简单的事情是正确的(X,10)
可以使用正则表达式: 子字符串(X,'。{0,10} $')
您甚至可以像这样nakostylyat “躲避”(在所有意义上): 反向(子字符串(反向(X)为10))


4.2存在一个带有文本列“ X”的表“ table_6”。 该表包含一行(所有文本均为英文和俄文):
 'Lorem 3 Ipsum 23 standard 7 dummy 17 text Ultimate Answer of Life ?? 777' 

A)编写一个查询,该查询将从该字符串返回第42至68个字符
B)如何使用SQL仅提取字符串中的大写字母(俄语或英语)?
C)如何使用SQL计算字符串中的数字总和( 不是数字

SQL草图
 WITH table_6(X) AS( SELECT 'Lorem 3 Ipsum 23 standard 7 dummy 17 text Ultimate Answer of Life ?? 777'::TEXT ) SELECT X FROM table_6 

答案4.2
  --    WITH  "SQL " -- ) SELECT SUBSTRING(LEFT(X,68) FROM 42 ) FROM table_6 -- 1  SELECT SUBSTRING(X, 42, (68-42)+1) FROM table_6 -- 2  -- 3    -- )  ,        SELECT regexp_replace(X,'[^A-Z-]', '','g') FROM table_6 --  ''      - --   'g'    1  -- )        --   regexp_matches   **     ,      SELECT sum(x[1]::INT) FROM ( SELECT regexp_matches(X,'[0-9]+','g') FROM table_6 ) AS y(x) -- *        -- **   +,     (   1 ,     ) 


4.3。如何用文本(表格单元格)中的单个空格替换所有双(三倍或更多)空格? (按照传统:表“ table_7 ”和“ X ”列)(PS足以写返回所需结果的SELECT ,而不是UPDATE table_7 ...

回复4.3
 WITH table_7(X) AS (SELECT 'Lorem 3 Ipsum 23 standard 7 dummy 11 text'::TEXT) -- 1 .    (2   ) SELECT regexp_replace(X, '( ){2,}', ' ', 'g') FROM table_7 -- 2 .     (,  ,    ..)   ,      SELECT regexp_replace(X, '\s+', ' ', 'g') FROM table_7 --  !  ,  -    ,    "" .    .. --   ,    , ,        --    ,      ,    SELECT replace(replace(replace(X, ' ', '<>'), '><', ''), '<>', ' ') FROM table_7 


4.4存在一个允许输入错误的字符串“ X ”。 代替俄语字母(e,o,s,C),使用了英文字母的向外相似字符。 将这些字符替换为SQL。

PS该行应仅包含俄语字符,并且您不必担心英语单词可能会发生变化。

(如果您难以替换所有字符,则至少替换一个)

示例行:

X = 'Coeo eoc oe'

回复4.4
 -- , Replace(Replace(Replace(..  ,  --        (1   1 ) SELECT TRANSLATE('Coeo  eoc oe', 'Cceo', '') 

4.5编写一个转换字符串的查询:
' 伊万·伊万诺夫和伊万诺维奇'到物种'伊万·伊万诺夫

回复4.5
 --  ,     SELECT initcap('  ') *      

对那些应付的人的奖励
如果有现成的功能,那就太好了
您能换一种方式吗? (最好不要丢失填充)。
也许任务不是典型的,但对开发很有用。

'IVANOV IVAN IVANOVICH'转换为'IVANOV IVAN IVANOVICH'
并反转大小写?

奖励挑战响应
 SELECT string_agg(LOWER(LEFT(x,1)) || UPPER(SUBSTRING(x from 2)), '' ORDER BY rn) FROM (SELECT * FROM regexp_split_to_table('    4 TesT', '\y') WITH ORDINALITY y(x, rn) ) AS z -- *  PostgreSQL,      --    ,     --      ,      --      . -- WITH ORDINALITY      (   9.4) --      --          -- .. 

5.关于交易的一点


在DBMS中,交易是非常重要的事情;了解要点很重要。

我将尝试模拟一个示例:

假设有一个“商品”表,两个用户将使用该表进行工作。
对于所有行,它都有一个等于10的整数折扣列。
数据库设置是标准的(READ COMMITTED-读取提交的数据)。

用户User_1打开一个事务,执行以下请求:

 BEGIN; UPDATE goods SET discount = discount + 5; 

一秒钟后,另一个用户( User_2
它执行几乎相同的请求而无需打开事务:
 UPDATE goods SET discount = discount + 10; 

您认为在以下情况下会发生什么:

A)如果User_1保留交易未打开(即不确认交易/不回滚更改),User_2将得到什么结果?
User_1会应要求看到的内容:

 SELECT discount FROM goods LIMIT 1; 

B)如果User_1做ROLLBACK会怎样? User_2将得到什么结果?

问)如果User_1进行COMMIT会怎样? User_2将得到什么结果?

答案
据我所知,PostgreSQL不支持READ UN COMMITTED,并且脏数据(未确认)无法读取

答案如下:

A)请求User_2将等待User_1的COMMIT或ROLLBACK。 (该请求似乎冻结了)
交易中的User_1将看到他的数据库快照版本,其中折扣已经等于15

B)如果User_1进行ROLLBACK,则折扣值将保持不变,然后执行User_2,这将为折扣加10,折扣为20

C)如果User_1执行COMMIT,则折扣值将增加5,然后执行User_2,这将为折扣加10,折扣为25

此任务的另一个版本
任务13与用户kirill_petrov在READ COMMITTED上的版本稍有不同
 --      CREATE TABLE goods (discount) AS (SELECT 10::INT UNION ALL SELECT 15); -- 1. User_1   (  ): BEGIN; UPDATE goods SET discount = discount + 5; --2. User_2  : UPDATE goods SET discount = discount + 100 WHERE discount = 15 --3. User_1  COMMIT; 
表格中将包含哪些数据?

结论


我认为这涉及到非常有趣的观点。

我希望这些任务将有助于激发初学者,因为学习没有特定目标/目的/方向的东西很无聊。

我为那些容易回答所有问题的人感到高兴。 我希望那些遇到困难的人能够朝着发展方向发展。 那些不太了解但想学习SQL的人,我在上一篇文章中邀请PostgreSQL少年战士课程

我期待对特别有趣的问题(您可以挖掘)的任何补充,解决方案以及其他意见!

感谢您的关注! 祝您学习SQL成功!

Source: https://habr.com/ru/post/zh-CN423097/


All Articles