[SQL] 두 테이블 사이의 수익률 차이에 SQL 쿼리
SQL두 테이블 사이의 수익률 차이에 SQL 쿼리
나는 일부 데이터를 확인하기 위해 두 개의 테이블, SQL Server를 비교하려합니다. 나는 데이터가 하나 또는 다른에 하나입니다 두 테이블의 모든 행을 반환하고자합니다. 본질적으로, 나는 모든 차이를 보여주고 싶어요. 그래서, 이름, 성 및 제품을하고 데이터의 세 가지를 확인해야합니다.
나는 SQL에 비교적 새로운 해요 그리고 내가 이상 일을 복잡하게되어 찾는거야 솔루션의 많은 것 같다. 나는 널 (NULL)에 대해 걱정할 필요가 없습니다.
나는 이런 식으로 뭔가를 시도하여 시작 :
SELECT DISTINCT [First Name], [Last Name], [Product Name] FROM [Temp Test Data]
WHERE ([First Name] NOT IN (SELECT [First Name]
FROM [Real Data]))
나는 문제가이 더 생각을 복용하는 데 문제가 있습니다.
감사!
편집하다:
나는 다음과 같은 쿼리의 변형을 사용하려고 한 @treaschf로 답변에 따라 :
SELECT td.[First Name], td.[Last Name], td.[Product Name]
FROM [Temp Test Data] td FULL OUTER JOIN [Data] AS d
ON td.[First Name] = d.[First Name] AND td.[Last Name] = d.[Last Name]
WHERE (d.[First Name] = NULL) AND (d.[Last Name] = NULL)
그러나 나는 D에없는 TD 적어도 1 개 행이 있다는 것을 알게되면, 다시 0 결과를 얻는 유지한다.
편집하다:
좋아, 내가 그것을 알아 냈다고 생각합니다. 테스트 내 몇 분 적어도 충분한을 작동하는 것 같다.
SELECT [First Name], [Last Name]
FROM [Temp Test Data] AS td
WHERE (NOT EXISTS
(SELECT [First Name], [Last Name]
FROM [Data] AS d
WHERE ([First Name] = td.[First Name]) OR ([Last Name] = td.[Last Name])))
이것은 기본적으로 내 실제 데이터가 아닌 내 테스트 데이터가 무엇인지 말해 줄 것입니다. 어느 내가 무엇을해야하는지에 대해 완전히 괜찮습니다.
해결법
-
==============================
1.당신이 테이블 A와 B, 콜 럼의 C에 모두있는 경우, 여기에 테이블 A에서가 아니라 B에 존재하는 기록이다 :
당신이 테이블 A와 B, 콜 럼의 C에 모두있는 경우, 여기에 테이블 A에서가 아니라 B에 존재하는 기록이다 :
SELECT A.* FROM A LEFT JOIN B ON (A.C = B.C) WHERE B.C IS NULL
단일 쿼리의 모든 차이를 얻으려면, 전체는 다음과 같이 사용해야합니다 조인 :
SELECT A.*, B.* FROM A FULL JOIN B ON (A.C = B.C) WHERE A.C IS NULL OR B.C IS NULL
당신이이 경우에 알 필요가있다, 그 기록은 발견 할 수있는 경우가 아닌 B에서 A의 B에서 온 열이 유사 B에 존재하는 사람들을위한하지 NULL, 그리고 것보다 , A로부터 열이 null이됩니다.
-
==============================
2.
( SELECT * FROM table1 EXCEPT SELECT * FROM table2) UNION ALL ( SELECT * FROM table2 EXCEPT SELECT * FROM table1)
-
==============================
3.나는이 인기가 해답이 될 수 없습니다 것을 알고 있지만 좀 더 복잡한 비교가 필요한 경우 타사 도구를 사용하여 @Randy 마인더에 동의 않습니다.
나는이 인기가 해답이 될 수 없습니다 것을 알고 있지만 좀 더 복잡한 비교가 필요한 경우 타사 도구를 사용하여 @Randy 마인더에 동의 않습니다.
여기이 특정 케이스는 쉽고 같은 도구가 필요하지 않습니다이 경우입니다하지만 당신은 두 개의 서버, 더 복잡한 비교 기준 등에 더 많은 열, 데이터베이스를 소개하는 경우이 쉽게 복잡한 얻을 수 있습니다.
이 같은 ApexSQL 데이터 DIFF 또는 퀘스트 두꺼비 이러한 도구 많이 있습니다 그리고 당신은 항상 작업을 완수하기 위해 시험 모드로 사용할 수 있습니다.
-
==============================
4.두 테이블 사이의 모든 차이를 얻으려면, 당신은 나처럼이 SQL 요청을 사용할 수 있습니다 :
두 테이블 사이의 모든 차이를 얻으려면, 당신은 나처럼이 SQL 요청을 사용할 수 있습니다 :
SELECT 'TABLE1-ONLY' AS SRC, T1.* FROM ( SELECT * FROM Table1 EXCEPT SELECT * FROM Table2 ) AS T1 UNION ALL SELECT 'TABLE2-ONLY' AS SRC, T2.* FROM ( SELECT * FROM Table2 EXCEPT SELECT * FROM Table1 ) AS T2 ;
-
==============================
5.쇼하는 테이블 행에 있는지 @erikkallen 대답에 간단한 변화 :
쇼하는 테이블 행에 있는지 @erikkallen 대답에 간단한 변화 :
( SELECT 'table1' as source, * FROM table1 EXCEPT SELECT * FROM table2) UNION ALL ( SELECT 'table2' as source, * FROM table2 EXCEPT SELECT * FROM table1)
당신은 오류가 발생하는 경우
다음은 추가하는 데 도움이 될 수 있습니다
( SELECT 'table1' as source, * FROM table1 EXCEPT SELECT 'table1' as source, * FROM table2) UNION ALL ( SELECT 'table2' as source, * FROM table2 EXCEPT SELECT 'table2' as source, * FROM table1)
-
==============================
6.당신이 열 값이 다른 어떤 얻고 싶은 경우에, 당신은 엔티티 - 속성 - 값 모델을 사용할 수 있습니다 :
당신이 열 값이 다른 어떤 얻고 싶은 경우에, 당신은 엔티티 - 속성 - 값 모델을 사용할 수 있습니다 :
declare @Data1 xml, @Data2 xml select @Data1 = ( select * from (select * from Test1 except select * from Test2) as a for xml raw('Data') ) select @Data2 = ( select * from (select * from Test2 except select * from Test1) as a for xml raw('Data') ) ;with CTE1 as ( select T.C.value('../@ID', 'bigint') as ID, T.C.value('local-name(.)', 'nvarchar(128)') as Name, T.C.value('.', 'nvarchar(max)') as Value from @Data1.nodes('Data/@*') as T(C) ), CTE2 as ( select T.C.value('../@ID', 'bigint') as ID, T.C.value('local-name(.)', 'nvarchar(128)') as Name, T.C.value('.', 'nvarchar(max)') as Value from @Data2.nodes('Data/@*') as T(C) ) select isnull(C1.ID, C2.ID) as ID, isnull(C1.Name, C2.Name) as Name, C1.Value as Value1, C2.Value as Value2 from CTE1 as C1 full outer join CTE2 as C2 on C2.ID = C1.ID and C2.Name = C1.Name where not ( C1.Value is null and C2.Value is null or C1.Value is not null and C2.Value is not null and C1.Value = C2.Value )
SQL 뿐인 예
-
==============================
7.이 시도 :
이 시도 :
SELECT [First Name], [Last Name] FROM [Temp Test Data] AS td EXCEPTION JOIN [Data] AS d ON (d.[First Name] = td.[First Name] OR d.[Last Name] = td.[Last Name])
읽기가 훨씬 간단합니다.
-
==============================
8.이 티아구의 솔루션, 반환 "소스"테이블 비슷한 트릭을뿐만 아니라 할 것입니다.
이 티아구의 솔루션, 반환 "소스"테이블 비슷한 트릭을뿐만 아니라 할 것입니다.
select [First name], [Last name], max(_tabloc) as _tabloc from ( select [First Name], [Last name], 't1' as _tabloc from table1 union all select [First name], [Last name], 't2' as _tabloc from table2 ) v group by [Fist Name], [Last name] having count(1)=1
당신이 테이블 참조를해야합니다 _tabloc 결과는 열의 테이블 사이의 차이를, 포함됩니다.
-
==============================
9.이 같은 예를 들어 뭔가를 제외하고 사용할 수 있습니다 :
이 같은 예를 들어 뭔가를 제외하고 사용할 수 있습니다 :
-- DB1..Tb1 have values than DB2..Tb1 not have Select Col1,Col2,Col3 From DB1..Tb1 except Select Col1,Col2,Col3 From DB2..Tb1 -- Now we change order -- DB2..Tb1 have values than DB1..Tb1 not have Select Col1,Col2,Col3 From DB2..Tb1 except Select Col1,Col2,Col3 From DB1..Tb1
-
==============================
10.당신이 열 이름에 대한 걱정에서 두 개의 테이블 / w를 일치하기 위해 노력하고 간단한 연기 테스트의 경우 :
당신이 열 이름에 대한 걱정에서 두 개의 테이블 / w를 일치하기 위해 노력하고 간단한 연기 테스트의 경우 :
--ensure tables have matching records Select count (*) from tbl_A Select count (*) from tbl_B --create temp table of all records in both tables Select * into #demo from tbl_A Union All Select * from tbl_B --Distinct #demo records = Total #demo records/2 = Total tbl_A records = total tbl_B records Select distinct * from #demo
당신은 쉽게 테이블의 배치를 비교하기 위해 저장 프로 시저를 작성 할 수 있습니다.
-
==============================
11.SP에 같은 차이점의 캐딜락을 제시. @erikkallen 의해 답변을 기반으로 한 기본 템플릿에서 참조하십시오. 그것은 지원
SP에 같은 차이점의 캐딜락을 제시. @erikkallen 의해 답변을 기반으로 한 기본 템플릿에서 참조하십시오. 그것은 지원
exec Common.usp_DiffTableRows '#t1', '#t2'; exec Common.usp_DiffTableRows @pTable0 = 'ydb.ysh.table1', @pTable1 = 'xdb.xsh.table2', @pOrderByCsvOpt = null, -- Order the results @pOnlyCsvOpt = null, -- Only compare these columns @pIgnoreCsvOpt = null; -- Ignore these columns (ignored if @pOnlyCsvOpt is specified)
alter proc [Common].[usp_DiffTableRows] @pTable0 varchar(300), @pTable1 varchar(300), @pOrderByCsvOpt nvarchar(1000) = null, -- Order the Results @pOnlyCsvOpt nvarchar(4000) = null, -- Only compare these columns @pIgnoreCsvOpt nvarchar(4000) = null, -- Ignore these columns (ignored if @pOnlyCsvOpt is specified) @pDebug bit = 0 as /*--------------------------------------------------------------------------------------------------------------------- Purpose: Compare rows between two tables. Usage: exec Common.usp_DiffTableRows '#a', '#b'; Modified By Description ---------- ---------- ------------------------------------------------------------------------------------------- 2015.10.06 crokusek Initial Version 2019.03.13 crokusek Added @pOrderByCsvOpt 2019.06.26 crokusek Support for @pIgnoreCsvOpt, @pOnlyCsvOpt. 2019.09.04 crokusek Minor debugging improvement 2020.03.12 crokusek Detect duplicate rows in either source table ---------------------------------------------------------------------------------------------------------------------*/ begin try if (substring(@pTable0, 1, 1) = '#') set @pTable0 = 'tempdb..' + @pTable0; -- object_id test below needs full names for temp tables if (substring(@pTable1, 1, 1) = '#') set @pTable1 = 'tempdb..' + @pTable1; -- object_id test below needs full names for temp tables if (object_id(@pTable0) is null) raiserror('Table name is not recognized: ''%s''', 16, 1, @pTable0); if (object_id(@pTable1) is null) raiserror('Table name is not recognized: ''%s''', 16, 1, @pTable1); create table #ColumnGathering ( Name nvarchar(300) not null, Sequence int not null, TableArg tinyint not null ); declare @usp varchar(100) = object_name(@@procid), @sql nvarchar(4000), @sqlTemplate nvarchar(4000) = ' use $database$; insert into #ColumnGathering select Name, column_id as Sequence, $TableArg$ as TableArg from sys.columns c where object_id = object_id(''$table$'', ''U'') '; set @sql = replace(replace(replace(@sqlTemplate, '$TableArg$', 0), '$database$', (select DatabaseName from Common.ufn_SplitDbIdentifier(@pTable0))), '$table$', @pTable0); if (@pDebug = 1) print 'Sql #CG 0: ' + @sql; exec sp_executesql @sql; set @sql = replace(replace(replace(@sqlTemplate, '$TableArg$', 1), '$database$', (select DatabaseName from Common.ufn_SplitDbIdentifier(@pTable1))), '$table$', @pTable1); if (@pDebug = 1) print 'Sql #CG 1: ' + @sql; exec sp_executesql @sql; if (@pDebug = 1) select * from #ColumnGathering; select Name, min(Sequence) as Sequence, convert(bit, iif(min(TableArg) = 0, 1, 0)) as InTable0, convert(bit, iif(max(TableArg) = 1, 1, 0)) as InTable1 into #Columns from #ColumnGathering group by Name having ( @pOnlyCsvOpt is not null and Name in (select Value from Common.ufn_UsvToNVarcharKeyTable(@pOnlyCsvOpt, default))) or ( @pOnlyCsvOpt is null and @pIgnoreCsvOpt is not null and Name not in (select Value from Common.ufn_UsvToNVarcharKeyTable(@pIgnoreCsvOpt, default))) or ( @pOnlyCsvOpt is null and @pIgnoreCsvOpt is null) if (exists (select 1 from #Columns where InTable0 = 0 or InTable1 = 0)) begin select 1; -- without this the debugging info doesn't stream sometimes select * from #Columns order by Sequence; waitfor delay '00:00:02'; -- give results chance to stream before raising exception raiserror('Columns are not equal between tables, consider using args @pIgnoreCsvOpt, @pOnlyCsvOpt. See Result Sets for details.', 16, 1); end if (@pDebug = 1) select * from #Columns order by Sequence; declare @columns nvarchar(4000) = --iif(@pOnlyCsvOpt is null and @pIgnoreCsvOpt is null, -- '*', ( select substring((select ',' + ac.name from #Columns ac order by Sequence for xml path('')),2,200000) as csv ); if (@pDebug = 1) begin print 'Columns: ' + @columns; waitfor delay '00:00:02'; -- give results chance to stream before possibly raising exception end -- Based on https://stackoverflow.com/a/2077929/538763 -- - Added sensing for duplicate rows -- - Added reporting of source table location -- set @sqlTemplate = ' with a as (select ~, Row_Number() over (partition by ~ order by (select null)) -1 as Duplicates from $a$), b as (select ~, Row_Number() over (partition by ~ order by (select null)) -1 as Duplicates from $b$) select 0 as SourceTable, ~ from ( select * from a except select * from b ) anb union all select 1 as SourceTable, ~ from ( select * from b except select * from a ) bna order by $orderBy$ '; set @sql = replace(replace(replace(replace(@sqlTemplate, '$a$', @pTable0), '$b$', @pTable1), '~', @columns), '$orderBy$', coalesce(@pOrderByCsvOpt, @columns + ', SourceTable') ); if (@pDebug = 1) print 'Sql: ' + @sql; exec sp_executesql @sql; end try begin catch declare @CatchingUsp varchar(100) = object_name(@@procid); if (xact_state() = -1) rollback; -- Disabled for S.O. post --exec Common.usp_Log --@pMethod = @CatchingUsp; --exec Common.usp_RethrowError --@pCatchingMethod = @CatchingUsp; throw; end catch go create function Common.Trim ( @pOriginalString nvarchar(max), @pCharsToTrim nvarchar(50) = null -- specify null or 'default' for whitespae ) returns table with schemabinding as /*-------------------------------------------------------------------------------------------------- Purpose: Trim the specified characters from a string. Modified By Description ---------- -------------- -------------------------------------------------------------------- 2012.09.25 S.Rutszy/crok Modified from https://dba.stackexchange.com/a/133044/9415 --------------------------------------------------------------------------------------------------*/ return with cte AS ( select patindex(N'%[^' + EffCharsToTrim + N']%', @pOriginalString) AS [FirstChar], patindex(N'%[^' + EffCharsToTrim + N']%', reverse(@pOriginalString)) AS [LastChar], len(@pOriginalString + N'~') - 1 AS [ActualLength] from ( select EffCharsToTrim = coalesce(@pCharsToTrim, nchar(0x09) + nchar(0x20) + nchar(0x0d) + nchar(0x0a)) ) c ) select substring(@pOriginalString, [FirstChar], ((cte.[ActualLength] - [LastChar]) - [FirstChar] + 2) ) AS [TrimmedString] -- --cte.[ActualLength], --[FirstChar], --((cte.[ActualLength] - [LastChar]) + 1) AS [LastChar] from cte; go create function [Common].[ufn_UsvToNVarcharKeyTable] ( @pCsvList nvarchar(MAX), @pSeparator nvarchar(1) = ',' -- can pass keyword 'default' when calling using ()'s ) -- -- SQL Server 2012 distinguishes nvarchar keys up to maximum of 450 in length (900 bytes) -- returns @tbl table (Value nvarchar(450) not null primary key(Value)) as /*------------------------------------------------------------------------------------------------- Purpose: Converts a comma separated list of strings into a sql NVarchar table. From http://www.programmingado.net/a-398/SQL-Server-parsing-CSV-into-table.aspx This may be called from RunSelectQuery: GRANT SELECT ON Common.ufn_UsvToNVarcharTable TO MachCloudDynamicSql; Modified By Description ---------- -------------- ------------------------------------------------------------------- 2011.07.13 internet Initial version 2011.11.22 crokusek Support nvarchar strings and a custom separator. 2017.12.06 crokusek Trim leading and trailing whitespace from each element. 2019.01.26 crokusek Remove newlines -------------------------------------------------------------------------------------------------*/ begin declare @pos int, @textpos int, @chunklen smallint, @str nvarchar(4000), @tmpstr nvarchar(4000), @leftover nvarchar(4000), @csvList nvarchar(max) = iif(@pSeparator not in (char(13), char(10), char(13) + char(10)), replace(replace(@pCsvList, char(13), ''), char(10), ''), @pCsvList); -- remove newlines set @textpos = 1 set @leftover = '' while @textpos <= len(@csvList) begin set @chunklen = 4000 - len(@leftover) set @tmpstr = ltrim(@leftover + substring(@csvList, @textpos, @chunklen)) set @textpos = @textpos + @chunklen set @pos = charindex(@pSeparator, @tmpstr) while @pos > 0 begin set @str = substring(@tmpstr, 1, @pos - 1) set @str = (select TrimmedString from Common.Trim(@str, default)); insert @tbl (value) values(@str); set @tmpstr = ltrim(substring(@tmpstr, @pos + 1, len(@tmpstr))) set @pos = charindex(@pSeparator, @tmpstr) end set @leftover = @tmpstr end -- Handle @leftover set @str = (select TrimmedString from Common.Trim(@leftover, default)); if @str <> '' insert @tbl (value) values(@str); return end GO create function Common.ufn_SplitDbIdentifier(@pIdentifier nvarchar(300)) returns @table table ( InstanceName nvarchar(300) not null, DatabaseName nvarchar(300) not null, SchemaName nvarchar(300), BaseName nvarchar(300) not null, FullTempDbBaseName nvarchar(300), -- non-null for tempdb (e.g. #Abc____...) InstanceWasSpecified bit not null, DatabaseWasSpecified bit not null, SchemaWasSpecified bit not null, IsCurrentInstance bit not null, IsCurrentDatabase bit not null, IsTempDb bit not null, OrgIdentifier nvarchar(300) not null ) as /*----------------------------------------------------------------------------------------------------------- Purpose: Split a Sql Server Identifier into its parts, providing appropriate default values and handling temp table (tempdb) references. Example: select * from Common.ufn_SplitDbIdentifier('t') union all select * from Common.ufn_SplitDbIdentifier('s.t') union all select * from Common.ufn_SplitDbIdentifier('d.s.t') union all select * from Common.ufn_SplitDbIdentifier('i.d.s.t') union all select * from Common.ufn_SplitDbIdentifier('#d') union all select * from Common.ufn_SplitDbIdentifier('tempdb..#d'); -- Empty select * from Common.ufn_SplitDbIdentifier('illegal name'); Modified By Description ---------- -------------- ----------------------------------------------------------------------------- 2013.09.27 crokusek Initial version. -----------------------------------------------------------------------------------------------------------*/ begin declare @name nvarchar(300) = ltrim(rtrim(@pIdentifier)); -- Return an empty table as a "throw" -- --Removed for SO post --if (Common.ufn_IsSpacelessLiteralIdentifier(@name) = 0) -- return; -- Find dots starting from the right by reversing first. declare @revName nvarchar(300) = reverse(@name); declare @firstDot int = charindex('.', @revName); declare @secondDot int = iif(@firstDot = 0, 0, charindex('.', @revName, @firstDot + 1)); declare @thirdDot int = iif(@secondDot = 0, 0, charindex('.', @revName, @secondDot + 1)); declare @fourthDot int = iif(@thirdDot = 0, 0, charindex('.', @revName, @thirdDot + 1)); --select @firstDot, @secondDot, @thirdDot, @fourthDot, len(@name); -- Undo the reverse() (first dot is first from the right). -- set @firstDot = iif(@firstDot = 0, 0, len(@name) - @firstDot + 1); set @secondDot = iif(@secondDot = 0, 0, len(@name) - @secondDot + 1); set @thirdDot = iif(@thirdDot = 0, 0, len(@name) - @thirdDot + 1); set @fourthDot = iif(@fourthDot = 0, 0, len(@name) - @fourthDot + 1); --select @firstDot, @secondDot, @thirdDot, @fourthDot, len(@name); declare @baseName nvarchar(300) = substring(@name, @firstDot + 1, len(@name) - @firstdot); declare @schemaName nvarchar(300) = iif(@firstDot - @secondDot - 1 <= 0, null, substring(@name, @secondDot + 1, @firstDot - @secondDot - 1)); declare @dbName nvarchar(300) = iif(@secondDot - @thirdDot - 1 <= 0, null, substring(@name, @thirdDot + 1, @secondDot - @thirdDot - 1)); declare @instName nvarchar(300) = iif(@thirdDot - @fourthDot - 1 <= 0, null, substring(@name, @fourthDot + 1, @thirdDot - @fourthDot - 1)); with input as ( select coalesce(@instName, '[' + @@servername + ']') as InstanceName, coalesce(@dbName, iif(left(@baseName, 1) = '#', 'tempdb', db_name())) as DatabaseName, coalesce(@schemaName, iif(left(@baseName, 1) = '#', 'dbo', schema_name())) as SchemaName, @baseName as BaseName, iif(left(@baseName, 1) = '#', ( select [name] from tempdb.sys.objects where object_id = object_id('tempdb..' + @baseName) ), null) as FullTempDbBaseName, iif(@instName is null, 0, 1) InstanceWasSpecified, iif(@dbName is null, 0, 1) DatabaseWasSpecified, iif(@schemaName is null, 0, 1) SchemaWasSpecified ) insert into @table select i.InstanceName, i.DatabaseName, i.SchemaName, i.BaseName, i.FullTempDbBaseName, i.InstanceWasSpecified, i.DatabaseWasSpecified, i.SchemaWasSpecified, iif(i.InstanceName = '[' + @@servername + ']', 1, 0) as IsCurrentInstance, iif(i.DatabaseName = db_name(), 1, 0) as IsCurrentDatabase, iif(left(@baseName, 1) = '#', 1, 0) as IsTempDb, @name as OrgIdentifier from input i; return; end GO
-
==============================
12.뿐만 아니라 전체 대량의 데이터와 조인 왼쪽과 관련된 성능 문제가 있습니다.
뿐만 아니라 전체 대량의 데이터와 조인 왼쪽과 관련된 성능 문제가 있습니다.
내 생각에 이것은 최선의 솔루션입니다 :
select [First Name], count(1) e from (select * from [Temp Test Data] union all select * from [Temp Test Data 2]) a group by [First Name] having e = 1
from https://stackoverflow.com/questions/2077807/sql-query-to-return-differences-between-two-tables by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 일시적으로 제약을 해제 (MS SQL) (0) | 2020.03.28 |
---|---|
[SQL] MySQL은, 더 나은 NULL 또는 빈 문자열을 삽입하는? (0) | 2020.03.28 |
[SQL] SQL 쿼리에 의해 특정 데이터베이스의 모든 테이블 이름을 얻기? (0) | 2020.03.27 |
[SQL] DDL 및 DML은 무엇입니까? (0) | 2020.03.27 |
[SQL] 어떻게 mysqldump를에서 덤프 파일을 복원 할 수 있습니까? (0) | 2020.03.27 |